Skip to content

Commit 5002e8c

Browse files
beriberikixclaude
andcommitted
Stop pushing to the tap; it pulls now
The update-homebrew-formula job sent a repository_dispatch that needed a personal access token with write access to the tap. That token expired after a year, the dispatch returned 401, and the step reported success regardless — so v0.5.0 shipped with the formula still pointing at a release that had been deleted. The tap now runs formula-sync.yml on a schedule: it reads the latest release here, which is public and needs no credential, and commits with its own GITHUB_TOKEN. Nothing expires, and a missed run is corrected by the next one. The job is kept rather than deleted because post-release depends on it and reads its result; its body is now a note explaining where formula updates happen and how to trigger one immediately. No reference to HOMEBREW_TAP_DISPATCH_TOKEN remains, so that secret can be deleted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rmyikdjWveP99ZUCDLY89
1 parent 3e8bd3c commit 5002e8c

2 files changed

Lines changed: 27 additions & 130 deletions

File tree

.github/workflows/release.yml

Lines changed: 19 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -729,135 +729,27 @@ jobs:
729729
needs: [release-validation, create-release, generate-homebrew-metadata]
730730
if: always() && needs.create-release.result == 'success'
731731
steps:
732-
- name: 🏺 Starting Homebrew Formula Update
732+
# The tap pulls; this repository no longer pushes to it.
733+
#
734+
# This job used to send a repository_dispatch to homebrew-usbipd-mac, which needed
735+
# a personal access token with write access there. The token expired after a year,
736+
# the dispatch began returning 401, and the step reported success regardless — so
737+
# v0.5.0 shipped with the formula still pointing at a deleted release.
738+
#
739+
# homebrew-usbipd-mac now runs formula-sync.yml on a schedule: it reads the latest
740+
# release here, which is public and needs no credential, and commits with its own
741+
# GITHUB_TOKEN. Nothing expires, and a missed run is corrected by the next one.
742+
- name: 🏺 Homebrew formula updates by pull
733743
run: |
734-
echo "::notice title=Homebrew Update::Starting automated Homebrew formula update via repository dispatch"
735-
echo "🏺 This stage triggers formula update in the tap repository"
736-
echo "📊 Status: STARTING"
737-
738-
- name: Checkout code
739-
uses: actions/checkout@v4
740-
741-
- name: 📥 Download Homebrew Metadata
742-
uses: actions/download-artifact@v4
743-
with:
744-
name: homebrew-metadata-${{ needs.release-validation.outputs.version }}
745-
path: homebrew-metadata/
746-
747-
- name: 🔧 Extract Metadata for Dispatch
748-
id: extract-metadata
749-
run: |
750-
echo "::group::Metadata Extraction"
751-
echo "::notice title=Metadata::Extracting metadata for repository dispatch"
752-
753-
METADATA_FILE="homebrew-metadata/homebrew-metadata.json"
754-
755-
if [ ! -f "$METADATA_FILE" ]; then
756-
echo "::error title=Metadata Missing::Homebrew metadata file not found"
757-
exit 1
758-
fi
759-
760-
# Extract metadata fields using jq
761-
VERSION=$(jq -r '.metadata.version' "$METADATA_FILE")
762-
ARCHIVE_URL=$(jq -r '.metadata.archive_url' "$METADATA_FILE")
763-
BINARY_URL=$(jq -r '.metadata.binary_url' "$METADATA_FILE")
764-
SHA256=$(jq -r '.metadata.sha256' "$METADATA_FILE")
765-
TIMESTAMP=$(jq -r '.metadata.timestamp' "$METADATA_FILE")
766-
767-
echo "🔍 Extracted metadata:"
768-
echo " • Version: $VERSION"
769-
echo " • Archive URL: $ARCHIVE_URL"
770-
echo " • Binary URL: $BINARY_URL"
771-
echo " • SHA256: ${SHA256:0:16}..."
772-
echo " • Timestamp: $TIMESTAMP"
773-
774-
# Output for next step
775-
echo "version=$VERSION" >> $GITHUB_OUTPUT
776-
echo "archive_url=$ARCHIVE_URL" >> $GITHUB_OUTPUT
777-
echo "binary_url=$BINARY_URL" >> $GITHUB_OUTPUT
778-
echo "sha256=$SHA256" >> $GITHUB_OUTPUT
779-
echo "timestamp=$TIMESTAMP" >> $GITHUB_OUTPUT
780-
echo "::endgroup::"
781-
782-
- name: 🚀 Send Repository Dispatch
783-
run: |
784-
echo "::group::Repository Dispatch"
785-
echo "::notice title=Repository Dispatch::Sending formula update event to tap repository"
786-
787-
VERSION="${{ steps.extract-metadata.outputs.version }}"
788-
ARCHIVE_URL="${{ steps.extract-metadata.outputs.archive_url }}"
789-
BINARY_URL="${{ steps.extract-metadata.outputs.binary_url }}"
790-
SHA256="${{ steps.extract-metadata.outputs.sha256 }}"
791-
TIMESTAMP="${{ steps.extract-metadata.outputs.timestamp }}"
792-
PRERELEASE="${{ needs.release-validation.outputs.is-prerelease }}"
793-
794-
echo "🏺 Sending repository dispatch to tap repository..."
795-
echo " • Target: beriberikix/homebrew-usbipd-mac"
796-
echo " • Event: formula_update"
797-
echo " • Version: $VERSION"
798-
799-
# The token is a PAT with access to the tap repository. GITHUB_TOKEN cannot
800-
# write to another repository, so an absent secret means the dispatch silently
801-
# 401s — which is exactly what happened for v0.5.0.
802-
if [ -z "${{ secrets.HOMEBREW_TAP_DISPATCH_TOKEN }}" ]; then
803-
echo "::error title=Missing Token::HOMEBREW_TAP_DISPATCH_TOKEN is not set; the tap cannot be updated"
804-
exit 1
805-
fi
806-
807-
# Capture the status. Without this the step reported success on a 401 and the
808-
# formula sat pointing at a deleted release.
809-
HTTP_STATUS=$(curl -sS -o /tmp/dispatch-response.json -w '%{http_code}' \
810-
-X POST \
811-
-H "Authorization: token ${{ secrets.HOMEBREW_TAP_DISPATCH_TOKEN }}" \
812-
-H "Accept: application/vnd.github.v3+json" \
813-
-H "Content-Type: application/json" \
814-
https://api.github.com/repos/beriberikix/homebrew-usbipd-mac/dispatches \
815-
-d '{
816-
"event_type": "formula_update",
817-
"client_payload": {
818-
"version": "'"$VERSION"'",
819-
"binary_url": "'"$BINARY_URL"'",
820-
"sha256": "'"$SHA256"'",
821-
"timestamp": "'"$TIMESTAMP"'",
822-
"source_repository": "'"${{ github.repository }}"'",
823-
"source_workflow_run": "'"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"'",
824-
"triggered_by": "automated-release",
825-
"prerelease": '"$PRERELEASE"'
826-
}
827-
}')
828-
829-
# A successful dispatch is 204 No Content.
830-
if [ "$HTTP_STATUS" != "204" ]; then
831-
echo "::error title=Dispatch Failed::Tap dispatch returned HTTP $HTTP_STATUS"
832-
cat /tmp/dispatch-response.json 2>/dev/null || true
833-
echo ""
834-
echo "401 or 404 means HOMEBREW_TAP_DISPATCH_TOKEN is missing, expired, or"
835-
echo "lacks access to beriberikix/homebrew-usbipd-mac."
836-
echo "The formula will keep pointing at the previous release until this is fixed."
837-
exit 1
838-
fi
839-
840-
echo "::notice title=Dispatch Sent::Repository dispatch accepted (HTTP 204)"
841-
echo "✅ Formula update event dispatched to tap repository"
842-
echo "🔗 Monitor tap repository: https://github.com/beriberikix/homebrew-usbipd-mac/actions"
843-
echo "::endgroup::"
744+
echo "::notice title=Homebrew Update::The tap syncs itself; no dispatch is sent"
745+
echo "The formula is updated by formula-sync.yml in homebrew-usbipd-mac,"
746+
echo "which polls this repository's latest release every six hours."
747+
echo ""
748+
echo "To update immediately rather than waiting for the schedule:"
749+
echo " gh workflow run formula-sync.yml --repo beriberikix/homebrew-usbipd-mac"
750+
echo ""
751+
echo "Tap runs: https://github.com/beriberikix/homebrew-usbipd-mac/actions"
844752
845-
- name: ⏳ Wait for Formula Update
846-
run: |
847-
echo "::group::Formula Update Monitoring"
848-
echo "::notice title=Monitoring::Waiting for tap repository formula update"
849-
850-
echo "⏳ Allowing time for tap repository to process update..."
851-
echo " • Repository dispatch events are processed asynchronously"
852-
echo " • Tap repository workflow will validate and update formula"
853-
echo " • Check tap repository actions for detailed progress"
854-
855-
# Wait 30 seconds to allow dispatch to be processed
856-
sleep 30
857-
858-
echo "✅ Formula update dispatch completed"
859-
echo "🔍 Check tap repository for update status: https://github.com/beriberikix/homebrew-usbipd-mac/actions"
860-
echo "::endgroup::"
861753
862754
post-release:
863755
name: Post-Release Validation

Documentation/development/driver-free-release.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,14 @@ extensions inside the *calling app's* bundle and requires that bundle to live in
136136
`/Applications`, so a Homebrew prefix is never consulted. See
137137
`Sources/USBIPDCore/SystemExtension/README.md`.
138138

139-
The `install-system-extension` command has since been removed from the CLI, so the
140-
formula's `post_install` instruction to run it now names a command that does not exist.
141-
Removing that instruction and the staged sysext resource is what remains. That is a change in the tap repository, not here.
139+
Done: the system extension resource, its staging, and the `post_install` instruction
140+
were removed from the tap on 2026-08-06.
141+
142+
The formula is now kept current by `formula-sync.yml` in the tap, which polls this
143+
repository's latest release every six hours and commits with its own `GITHUB_TOKEN`.
144+
That replaced a `repository_dispatch` which needed a personal access token here — the
145+
token expired after a year, the dispatch returned 401, and the sending step reported
146+
success anyway, so v0.5.0 shipped with the formula pointing at a deleted release. That is a change in the tap repository, not here.
142147

143148
A cask is **not** needed for this release. It becomes the right vehicle only if a real
144149
DriverKit extension appears, since a dext must live in an app bundle in `/Applications`.

0 commit comments

Comments
 (0)