diff --git a/.github/workflows/publish-commit-bottles.yml b/.github/workflows/publish-commit-bottles.yml index 8bdba88ff3018..dc96f81438e83 100644 --- a/.github/workflows/publish-commit-bottles.yml +++ b/.github/workflows/publish-commit-bottles.yml @@ -2,6 +2,10 @@ name: Publish and commit bottles run-name: "Publish PR #${{ inputs.pull_request }}" +concurrency: + group: ${{ github.workflow }}-${{ inputs.pull_request }} + cancel-in-progress: false + on: workflow_dispatch: inputs: @@ -28,6 +32,7 @@ on: required: false env: + PR: ${{inputs.pull_request}} GNUPGHOME: /tmp/gnupghome HOMEBREW_DEVELOPER: 1 HOMEBREW_NO_AUTO_UPDATE: 1 @@ -39,35 +44,36 @@ env: NON_PUSHABLE_MESSAGE: ":no_entry: It looks like @BrewTestBot cannot push to your PR branch. Please [allow maintainers to edit your PR](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so that it can be merged." ORG_FORK_MESSAGE: ":no_entry: It looks like @BrewTestBot cannot push to your PR branch. Please open a new pull request from a non-organization fork so that it can be merged." -permissions: - contents: read - jobs: - upload: - runs-on: ${{inputs.large_runner && 'homebrew-large-bottle-upload' || 'ubuntu-22.04'}} - container: - image: ghcr.io/homebrew/ubuntu22.04:master - defaults: - run: - shell: bash + check: + runs-on: ubuntu-latest permissions: + contents: read pull-requests: write + outputs: + bottles: ${{steps.pr-branch-check.outputs.bottles}} + head_sha: ${{steps.pr-branch-check.outputs.head_sha}} + branch: ${{steps.pr-branch-check.outputs.branch}} + origin_branch: ${{steps.pr-branch-check.outputs.origin_branch}} + remote: ${{steps.pr-branch-check.outputs.remote}} steps: - - name: Set up Homebrew - id: set-up-homebrew - uses: Homebrew/actions/setup-homebrew@master - with: - test-bot: false - - name: Check PR approval env: GH_TOKEN: ${{secrets.GITHUB_TOKEN}} - PR: ${{inputs.pull_request}} run: | - reviews=() + approved=false + changes_requested=false while IFS='' read -r review do - reviews+=("$review") + if [[ "$review" = "APPROVED" ]] + then + approved=true + fi + + if [[ "$review" = "CHANGES_REQUESTED" ]] + then + changes_requested=true + fi done < <( gh api \ --header 'Accept: application/vnd.github+json' \ @@ -76,16 +82,7 @@ jobs: --jq '.[].state' ) - for review in "${reviews[@]}" - do - if [[ "$review" = "APPROVED" ]] - then - approved=1 - break - fi - done - - if [[ -z "$approved" ]] + if [[ "$approved" != "true" ]] || [[ "$changes_requested" = "true" ]] then echo "::error ::PR #$PR is not approved!" exit 1 @@ -95,7 +92,6 @@ jobs: id: pr-branch-check env: GH_TOKEN: ${{secrets.GITHUB_TOKEN}} - PR: ${{inputs.pull_request}} run: | pr_data="$( gh api \ @@ -111,55 +107,59 @@ jobs: head_repo_owner="$(jq --raw-output .head.repo.owner.login <<< "$pr_data")" head_sha="$(jq --raw-output .head.sha <<< "$pr_data")" fork_type="$(jq --raw-output .head.repo.owner.type <<< "$pr_data")" + merged="$(jq --raw-output .merged <<< "$pr_data")" + automerge_data="$(jq --raw-output .auto_merge <<< "$pr_data")" - labels=() - while IFS='' read -r label - do - labels+=("$label") - done < <(jq --raw-output '.labels[].name' <<< "$pr_data") - - # We don't check $labels here because it is empty if a PR has no labels. if [[ -z "$pushable" ]] || [[ -z "$branch" ]] || [[ -z "$remote" ]] || [[ -z "$head_repo" ]] || [[ -z "$head_repo_owner" ]] || [[ -z "$head_sha" ]] || - [[ -z "$fork_type" ]] + [[ -z "$fork_type" ]] || + [[ -z "$merged" ]] || + [[ -z "$automerge_data" ]] then echo "::error ::Failed to get PR data!" exit 1 fi - echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT" - bottles=true - for label in "${labels[@]}" + while IFS='' read -r label do - if [[ "$label" = "CI-syntax-only" ]] || [[ "$label" = "CI-no-bottles" ]] + if [[ "$label" = "CI-syntax-only" ]] || + [[ "$label" = "CI-no-bottles" ]] || + [[ "$label" = "CI-published-bottle-commits" ]] then echo '::notice ::No bottles to publish according to PR labels.' bottles=false break fi - done - echo "bottles=${bottles}" >> "$GITHUB_OUTPUT" + done < <(jq --raw-output '.labels[].name' <<< "$pr_data") - if [[ "$branch" = "master" ]] + if [[ "$merged" = "true" ]] || [[ -n "$automerge_data" ]] then - echo "branch=$head_repo_owner/master" >> "$GITHUB_OUTPUT" - else - echo "branch=$branch" >> "$GITHUB_OUTPUT" + bottles=false fi - echo "origin_branch=$branch" >> "$GITHUB_OUTPUT" - echo "remote=$remote" >> "$GITHUB_OUTPUT" - if [[ "$head_repo" = "$GH_REPO" ]] + if [[ "$branch" = "master" ]] then - exit 0 + branch="$head_repo_owner/master" + origin_branch="master" + else + origin_branch="$branch" fi - if "$pushable" && [[ "$fork_type" != "Organization" ]] + { + echo "bottles=$bottles" + echo "head_sha=$head_sha" + echo "branch=$branch" + echo "origin_branch=$origin_branch" + echo "remote=$remote" + } >> "$GITHUB_OUTPUT" + + if "$pushable" && [[ "$fork_type" != "Organization" ]] || + [[ "$head_repo" = "$GH_REPO" ]] then exit 0 elif "$pushable" @@ -173,16 +173,34 @@ jobs: gh pr edit --add-label 'no push access' "$PR" exit 1 + upload: + needs: check + if: fromJson(needs.check.outputs.bottles) + runs-on: ${{inputs.large_runner && 'homebrew-large-bottle-upload' || 'ubuntu-22.04'}} + container: + image: ghcr.io/homebrew/ubuntu22.04:master + permissions: + contents: write + pull-requests: write + defaults: + run: + shell: bash + steps: - name: Post comment once started - if: fromJson(steps.pr-branch-check.outputs.bottles) uses: Homebrew/actions/post-comment@master with: token: ${{secrets.GITHUB_TOKEN}} - issue: ${{github.event.inputs.pull_request}} + issue: ${{inputs.pull_request}} body: ":shipit: @${{github.actor}} has [requested bottles to be published to this PR](${{env.RUN_URL}})." bot_body: ":robot: A scheduled task has [requested bottles to be published to this PR](${{env.RUN_URL}})." bot: BrewTestBot + - name: Set up Homebrew + id: set-up-homebrew + uses: Homebrew/actions/setup-homebrew@master + with: + test-bot: false + - name: Configure Git user id: git-user-config uses: Homebrew/actions/git-user-config@master @@ -195,15 +213,13 @@ jobs: signing_key: ${{ secrets.BREWTESTBOT_GPG_SIGNING_SUBKEY }} - name: Checkout PR branch - if: fromJson(steps.pr-branch-check.outputs.bottles) working-directory: ${{steps.set-up-homebrew.outputs.repository-path}} env: GH_TOKEN: ${{secrets.GITHUB_TOKEN}} - run: gh pr checkout '${{github.event.inputs.pull_request}}' + run: gh pr checkout "$PR" - name: Pull and upload bottles to GitHub Packages id: pr-pull - if: fromJson(steps.pr-branch-check.outputs.bottles) working-directory: ${{steps.set-up-homebrew.outputs.repository-path}} env: BREWTESTBOT_NAME_EMAIL: "${{ steps.git-user-config.outputs.name }} <${{ steps.git-user-config.outputs.email }}>" @@ -211,10 +227,10 @@ jobs: HOMEBREW_GITHUB_API_TOKEN: ${{secrets.HOMEBREW_CORE_PUBLIC_REPO_EMAIL_TOKEN}} HOMEBREW_GITHUB_PACKAGES_USER: brewtestbot HOMEBREW_GITHUB_PACKAGES_TOKEN: ${{secrets.HOMEBREW_CORE_GITHUB_PACKAGES_TOKEN}} - EXPECTED_SHA: ${{steps.pr-branch-check.outputs.head_sha}} + EXPECTED_SHA: ${{needs.check.outputs.head_sha}} run: | local_git_head="$(git rev-parse HEAD)" - remote_git_head="$(git ls-remote origin 'pull/${{inputs.pull_request}}/head' | cut -f1)" + remote_git_head="$(git ls-remote origin "pull/$PR/head" | cut -f1)" if [ "$local_git_head" != "$EXPECTED_SHA" ] || [ "$remote_git_head" != "$EXPECTED_SHA" ] @@ -236,19 +252,18 @@ jobs: '${{inputs.autosquash && '--autosquash' || '--clean'}}' \ ${{inputs.warn_on_upload_failure && '--warn-on-upload-failure' || ''}} \ ${{inputs.message && format('--message="{0}"', inputs.message) || ''}} \ - '${{github.event.inputs.pull_request}}' + "$PR" echo "head_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" - name: Push commits - if: fromJson(steps.pr-branch-check.outputs.bottles) uses: Homebrew/actions/git-try-push@master with: token: ${{secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN}} directory: ${{steps.set-up-homebrew.outputs.repository-path}} - remote: ${{steps.pr-branch-check.outputs.remote}} - branch: ${{steps.pr-branch-check.outputs.branch}} - origin_branch: ${{steps.pr-branch-check.outputs.origin_branch}} + remote: ${{needs.check.outputs.remote}} + branch: ${{needs.check.outputs.branch}} + origin_branch: ${{needs.check.outputs.origin_branch}} force: ${{inputs.autosquash}} no_lease: ${{inputs.autosquash}} env: @@ -257,8 +272,7 @@ jobs: HOMEBREW_GPG_PASSPHRASE: ${{ secrets.BREWTESTBOT_GPG_SIGNING_SUBKEY_PASSPHRASE }} - name: Add CI-published-bottle-commits label - if: fromJson(steps.pr-branch-check.outputs.bottles) - run: gh pr edit --add-label CI-published-bottle-commits '${{github.event.inputs.pull_request}}' + run: gh pr edit --add-label CI-published-bottle-commits "$PR" env: GH_TOKEN: ${{secrets.GITHUB_TOKEN}} working-directory: ${{steps.set-up-homebrew.outputs.repository-path}} @@ -268,7 +282,7 @@ jobs: uses: Homebrew/actions/post-comment@master with: token: ${{secrets.GITHUB_TOKEN}} - issue: ${{github.event.inputs.pull_request}} + issue: ${{inputs.pull_request}} body: ":warning: @${{github.actor}} bottle publish [failed](${{env.RUN_URL}}). CC @carlocab" bot_body: ":warning: Bottle publish [failed](${{env.RUN_URL}}). CC @carlocab" bot: BrewTestBot @@ -277,13 +291,12 @@ jobs: if: ${{!success()}} uses: Homebrew/actions/dismiss-approvals@master with: - token: ${{secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN}} - pr: ${{github.event.inputs.pull_request}} + token: ${{secrets.GITHUB_TOKEN}} + pr: ${{inputs.pull_request}} message: "bottle publish failed" - name: Wait until pull request branch is in sync with local repository id: wait-until-in-sync - if: fromJson(steps.pr-branch-check.outputs.bottles) working-directory: ${{steps.set-up-homebrew.outputs.repository-path}} env: EXPECTED_SHA: ${{steps.pr-pull.outputs.head_sha}} @@ -297,7 +310,7 @@ jobs: # Wait (with exponential backoff) until the PR branch is in sync while [[ "$attempt" -lt "$max_attempts" ]] do - remote_head="$(git ls-remote origin "pull/${{inputs.pull_request}}/head" | cut -f1)" + remote_head="$(git ls-remote origin "pull/$PR/head" | cut -f1)" echo "::notice ::Pull request HEAD: $remote_head" if [[ "$EXPECTED_SHA" = "$remote_head" ]] then @@ -311,22 +324,21 @@ jobs: done # One last check... - if [[ -z "$success" ]] && [[ "$EXPECTED_SHA" != "$(git ls-remote origin "pull/${{inputs.pull_request}}/head" | cut -f1)" ]] + if [[ -z "$success" ]] && [[ "$EXPECTED_SHA" != "$(git ls-remote origin "pull/$PR/head" | cut -f1)" ]] then echo "::error ::No attempts remaining. Giving up." exit 1 fi - name: Approve PR and enable automerge - if: fromJson(steps.pr-branch-check.outputs.bottles) id: automerge env: - GH_TOKEN: ${{secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN}} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} EXPECTED_SHA: ${{steps.pr-pull.outputs.head_sha}} working-directory: ${{steps.set-up-homebrew.outputs.repository-path}} run: | local_git_head="$(git rev-parse HEAD)" - remote_git_head="$(git ls-remote origin 'pull/${{inputs.pull_request}}/head' | cut -f1)" + remote_git_head="$(git ls-remote origin "pull/$PR/head" | cut -f1)" if [[ "$local_git_head" != "$EXPECTED_SHA" ]] || [[ "$remote_git_head" != "$EXPECTED_SHA" ]] @@ -338,8 +350,8 @@ jobs: exit 1 fi - gh pr merge --auto --merge '${{inputs.pull_request}}' - gh pr review --approve '${{inputs.pull_request}}' + gh pr merge --auto --merge "$PR" + gh pr review --approve "$PR" - name: Post comment on failure if: > @@ -349,7 +361,7 @@ jobs: uses: Homebrew/actions/post-comment@master with: token: ${{secrets.GITHUB_TOKEN}} - issue: ${{github.event.inputs.pull_request}} + issue: ${{inputs.pull_request}} body: ":warning: @${{github.actor}} [Failed to enable automerge](${{env.RUN_URL}}). CC @carlocab" bot_body: ":warning: [Failed to enable automerge](${{env.RUN_URL}}). CC @carlocab" bot: BrewTestBot