Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ env:
HOMEBREW_TAP_ENABLED: "false"
HOMEBREW_TAP_NAME: "eschaar/vstack"
HOMEBREW_TAP_REPOSITORY: "eschaar/homebrew-vstack"
HOMEBREW_TAP_REPOSITORY_OWNER: "eschaar"
HOMEBREW_TAP_REPOSITORY_NAME: "homebrew-vstack"
HOMEBREW_FORMULA_NAME: "vstack"
HOMEBREW_FULLY_QUALIFIED_FORMULA: "eschaar/vstack/vstack"

Expand Down Expand Up @@ -149,11 +151,14 @@ jobs:
publish-homebrew:
name: Update Homebrew Tap
needs: publish
if: needs.publish.result == 'success' && github.event.release.prerelease == false && env.HOMEBREW_TAP_ENABLED == 'true'
# NOTE: job-level `if` cannot use the `env` context. Toggle via repository variable
# HOMEBREW_TAP_ENABLED (value: "true" to enable). Default/absent keeps this disabled.
if: needs.publish.result == 'success' && github.event.release.prerelease == false && vars.HOMEBREW_TAP_ENABLED == 'true'
runs-on: ubuntu-latest
environment: pypi
environment: homebrew
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
HOMEBREW_TAP_APP_CLIENT_ID: ${{ secrets.HOMEBREW_TAP_APP_CLIENT_ID }}
HOMEBREW_TAP_APP_PRIVATE_KEY: ${{ secrets.HOMEBREW_TAP_APP_PRIVATE_KEY }}
HOMEBREW_TAP_DISPATCH_SECRET: ${{ secrets.HOMEBREW_TAP_DISPATCH_SECRET }}

steps:
Expand Down Expand Up @@ -181,11 +186,30 @@ jobs:
- name: Verify Homebrew tap dispatch configuration
shell: bash
run: |
if [[ -z "$HOMEBREW_TAP_TOKEN" ]]; then
echo "ERROR: HOMEBREW_TAP_TOKEN is not configured in the pypi environment."
if [[ -z "$HOMEBREW_TAP_APP_CLIENT_ID" ]]; then
echo "ERROR: HOMEBREW_TAP_APP_CLIENT_ID is not configured in the pypi environment."
exit 1
fi

if [[ -z "$HOMEBREW_TAP_APP_PRIVATE_KEY" ]]; then
echo "ERROR: HOMEBREW_TAP_APP_PRIVATE_KEY is not configured in the pypi environment."
exit 1
fi

if [[ -z "$HOMEBREW_TAP_DISPATCH_SECRET" ]]; then
echo "ERROR: HOMEBREW_TAP_DISPATCH_SECRET is not configured in the pypi environment."
exit 1
fi

- name: Create Homebrew tap app token
id: create_tap_token
uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349
with:
client-id: ${{ env.HOMEBREW_TAP_APP_CLIENT_ID }}
private-key: ${{ env.HOMEBREW_TAP_APP_PRIVATE_KEY }}
owner: ${{ env.HOMEBREW_TAP_REPOSITORY_OWNER }}
repositories: ${{ env.HOMEBREW_TAP_REPOSITORY_NAME }}

- name: Fetch sdist metadata and verify checksum
id: verify_sdist
shell: bash
Expand Down Expand Up @@ -264,7 +288,7 @@ jobs:

curl -fsS -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${HOMEBREW_TAP_TOKEN}" \
-H "Authorization: Bearer ${{ steps.create_tap_token.outputs.token }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/${HOMEBREW_TAP_REPOSITORY}/dispatches" \
--data-binary @dispatch-body.json
Expand Down
23 changes: 22 additions & 1 deletion tests/vstack/test_publish_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def test_homebrew_job_is_gated_and_sequential(self) -> None:
assert env["HOMEBREW_TAP_ENABLED"] == "false"
assert env["HOMEBREW_TAP_NAME"] == "eschaar/vstack"
assert env["HOMEBREW_TAP_REPOSITORY"] == "eschaar/homebrew-vstack"
assert env["HOMEBREW_TAP_REPOSITORY_OWNER"] == "eschaar"
assert env["HOMEBREW_TAP_REPOSITORY_NAME"] == "homebrew-vstack"
assert env["HOMEBREW_FORMULA_NAME"] == "vstack"
assert env["HOMEBREW_FULLY_QUALIFIED_FORMULA"] == "eschaar/vstack/vstack"

Expand All @@ -29,7 +31,7 @@ def test_homebrew_job_is_gated_and_sequential(self) -> None:
job_if = homebrew_job["if"]
assert "needs.publish.result == 'success'" in job_if
assert "github.event.release.prerelease == false" in job_if
assert "env.HOMEBREW_TAP_ENABLED == 'true'" in job_if
assert "vars.HOMEBREW_TAP_ENABLED == 'true'" in job_if

def test_homebrew_job_verifies_sdist_and_dispatches_update(self) -> None:
"""Homebrew publish should verify sdist checksum before repository dispatch."""
Expand All @@ -41,12 +43,31 @@ def test_homebrew_job_verifies_sdist_and_dispatches_update(self) -> None:
assert "https://pypi.org/pypi/vstack/" in verify_script
assert "sha256 mismatch between PyPI metadata and downloaded tarball" in verify_script

config_step = next(
step for step in steps if step["name"] == "Verify Homebrew tap dispatch configuration"
)
config_script = config_step["run"]
assert "HOMEBREW_TAP_APP_CLIENT_ID" in config_script
assert "HOMEBREW_TAP_APP_PRIVATE_KEY" in config_script
assert "HOMEBREW_TAP_DISPATCH_SECRET" in config_script

app_token_step = next(step for step in steps if step.get("id") == "create_tap_token")
assert (
app_token_step["uses"]
== "actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349"
)
assert app_token_step["with"]["client-id"] == "${{ env.HOMEBREW_TAP_APP_CLIENT_ID }}"
assert app_token_step["with"]["private-key"] == "${{ env.HOMEBREW_TAP_APP_PRIVATE_KEY }}"
assert app_token_step["with"]["owner"] == "${{ env.HOMEBREW_TAP_REPOSITORY_OWNER }}"
assert app_token_step["with"]["repositories"] == "${{ env.HOMEBREW_TAP_REPOSITORY_NAME }}"

dispatch_step = next(
step for step in steps if step["name"] == "Dispatch formula update to Homebrew tap"
)
dispatch_script = dispatch_step["run"]
assert "/dispatches" in dispatch_script
assert "dispatch-body.json" in dispatch_script
assert "steps.create_tap_token.outputs.token" in dispatch_script

step_env = dispatch_step["env"]
assert step_env["RELEASE_VERSION"] == "${{ github.event.release.tag_name }}"
Expand Down