Skip to content

Commit

Permalink
publish-commit-bottles: set concurrency
Browse files Browse the repository at this point in the history
This will make sure we only run one of these at a time for any given PR.

While we're here:
- add stricter checks to make sure we don't attempt to `pr-pull` PRs
  that we don't want or need to
- avoid looping over arrays twice when we don't need to
- improve readability by relying less on workflow expression interpolation
- use `GITHUB_TOKEN` more often
  • Loading branch information
carlocab committed Apr 18, 2023
1 parent 423c052 commit fd30058
Showing 1 changed file with 91 additions and 79 deletions.
170 changes: 91 additions & 79 deletions .github/workflows/publish-commit-bottles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -28,6 +32,7 @@ on:
required: false

env:
PR: ${{inputs.pull_request}}
GNUPGHOME: /tmp/gnupghome
HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1
Expand All @@ -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' \
Expand All @@ -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
Expand All @@ -95,7 +92,6 @@ jobs:
id: pr-branch-check
env:
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
PR: ${{inputs.pull_request}}
run: |
pr_data="$(
gh api \
Expand All @@ -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"
Expand All @@ -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
Expand All @@ -195,26 +213,24 @@ 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 }}>"
HOMEBREW_GPG_PASSPHRASE: ${{ secrets.BREWTESTBOT_GPG_SIGNING_SUBKEY_PASSPHRASE }}
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" ]
Expand All @@ -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:
Expand All @@ -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}}
Expand All @@ -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
Expand All @@ -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}}
Expand All @@ -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
Expand All @@ -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" ]]
Expand All @@ -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: >
Expand All @@ -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

0 comments on commit fd30058

Please sign in to comment.