feat(flag): Add --no-color flag to remove color from terminal output
#468
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: API Diff Check | |
| on: | |
| # SECURITY: Using pull_request_target to support fork PRs with write permissions. | |
| # PR code is checked out but only for static analysis - it is never executed. | |
| # If modifying this workflow, ensure PR code is never executed and user inputs are not used unsafely. | |
| pull_request_target: | |
| types: [opened, synchronize] | |
| paths: | |
| - 'pkg/**/*.go' | |
| - 'rpc/**/*.go' | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| apidiff: | |
| runs-on: ubuntu-24.04 | |
| name: API Diff Check | |
| steps: | |
| # Check if PR has conflicts. When conflicts exist, the merge commit becomes | |
| # frozen at an old state and apidiff cannot run correctly. | |
| - name: Check for merge conflicts | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| # pull_request_target and mergeability are processed asynchronously. | |
| # As a result, it’s possible that we start the check before GitHub has finished calculating the mergeability. | |
| # To handle this, a retry mechanism has been added — it waits for 2 seconds after each attempt. | |
| # If mergeable_state isn’t obtained after 5 attempts, an error is returned. | |
| run: | | |
| MAX=5 | |
| for i in $(seq 1 "$MAX"); do | |
| state=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER" --jq .mergeable_state) | |
| echo "mergeable_state=$state" | |
| if [ "$state" = "dirty" ]; then | |
| echo "::error::This PR has merge conflicts. Please resolve conflicts before running apidiff." | |
| exit 1 | |
| fi | |
| if [ -n "$state" ] && [ "$state" != "unknown" ] && [ "$state" != "null" ]; then | |
| break | |
| fi | |
| if [ "$i" -lt "$MAX" ] && { [ -z "$state" ] || [ "$state" = "unknown" ] || [ "$state" = "null" ]; }; then | |
| echo "::error::Could not determine mergeability after $i tries." | |
| exit 1 | |
| fi | |
| sleep 2 | |
| done | |
| # Checkout PR merge commit to compare against base branch | |
| # This ensures we compare the actual merge result with the base branch, | |
| # avoiding false positives when PR is not rebased with latest main | |
| - name: Checkout | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| ref: refs/pull/${{ github.event.pull_request.number }}/merge | |
| - name: Set up Go | |
| uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 | |
| with: | |
| go-version-file: go.mod | |
| check-latest: true # Ensure we use the latest Go patch version | |
| cache: false | |
| # Ensure the base commit exists locally for go-apidiff to compare against. | |
| # Even though we checkout the merge commit, go-apidiff needs the base ref to exist. | |
| # Use base.ref instead of base.sha, since base.sha is outdated (not updated after every commit). | |
| # cf. https://github.com/orgs/community/discussions/59677 | |
| - name: Fetch base commit | |
| id: fetch_base | |
| run: | | |
| set -euo pipefail | |
| BASE_REF="${{ github.event.pull_request.base.ref || github.event.merge_group.base_ref }}" | |
| if [ -z "${BASE_REF:-}" ]; then | |
| echo "::error::BASE_REF is empty (no base ref in event payload)"; exit 1 | |
| fi | |
| git fetch --depth=1 origin "$BASE_REF" | |
| BASE_SHA="$(git rev-parse "origin/$BASE_REF")" | |
| if [ -z "${BASE_SHA:-}" ]; then | |
| echo "::error::BASE_SHA is empty (failed to resolve origin/$BASE_REF)"; exit 1 | |
| fi | |
| echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT" | |
| # NOTE: go-apidiff is not managed in go.mod because installing it via `go get -tool` | |
| # would cause `mage tool:install` to attempt building it on Windows, which currently | |
| # fails due to platform-specific issues. | |
| - name: Run go-apidiff | |
| id: apidiff | |
| continue-on-error: true | |
| uses: joelanford/go-apidiff@60c4206be8f84348ebda2a3e0c3ac9cb54b8f685 # v0.8.3 | |
| with: | |
| base-ref: ${{ steps.fetch_base.outputs.base_sha }} | |
| version: v0.8.3 | |
| - name: Add apidiff label | |
| if: ${{ steps.apidiff.outputs.semver-type == 'major' }} | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const label = 'apidiff'; | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| labels: [label], | |
| }); | |
| - name: Comment API diff | |
| if: ${{ steps.apidiff.outputs.semver-type == 'major' }} | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| APIDIFF_OUTPUT: ${{ steps.apidiff.outputs.output }} | |
| SEMVER_TYPE: ${{ steps.apidiff.outputs.semver-type }} | |
| with: | |
| script: | | |
| const header = '## 📊 API Changes Detected'; | |
| const diff = process.env.APIDIFF_OUTPUT.trim(); | |
| const semver = process.env.SEMVER_TYPE || 'unknown'; | |
| const body = [ | |
| header, | |
| '', | |
| `Semver impact: \`${semver}\``, | |
| '', | |
| '```', | |
| diff, | |
| '```', | |
| ].join('\n'); | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const existing = comments.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.startsWith(header), | |
| ); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }); | |
| } | |
| # Attempt to request the premium reviewers; needs org-scoped token because GITHUB_TOKEN lacks read:org. | |
| - name: Request trivy-premium review | |
| if: ${{ steps.apidiff.outputs.semver-type == 'major' }} | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| github-token: ${{ secrets.ORG_REPO_TOKEN }} | |
| script: | | |
| try { | |
| await github.rest.pulls.requestReviewers({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.issue.number, | |
| team_reviewers: ['trivy-premium'], | |
| }); | |
| console.log('Requested review from aquasecurity/trivy-premium team'); | |
| } catch (error) { | |
| core.error(`Failed to request trivy-premium reviewers: ${error.message}`); | |
| throw error; | |
| } |