feat(cache): add top-level refresh subcommand (#146) #36
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: Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Tag to build (e.g., v1.0.0)' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| jobs: | |
| goreleaser: | |
| # INT-449: darwin must build with cgo (Keychain backend). cgo+darwin | |
| # cannot cross-compile from Linux, so this job runs on macOS. Pinned | |
| # image (not the moving macos-latest label) for a reproducible release. | |
| runs-on: macos-15 | |
| env: | |
| TAG: ${{ github.ref_name || inputs.tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ env.TAG }} | |
| fetch-depth: 0 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.26" | |
| - name: Install GoReleaser | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| version: "~> v2" | |
| install-only: true | |
| - name: GoReleaser check | |
| run: goreleaser check | |
| - name: Build (snapshot, no publish) | |
| run: goreleaser release --snapshot --clean | |
| # INT-449 pre-publish gate: prove the darwin binaries actually carry | |
| # the Keychain backend BEFORE anything is published. A CGO_ENABLED=0 | |
| # darwin build links no Security.framework and fails closed at | |
| # runtime; this gate makes that impossible to ship silently. | |
| - name: Pre-publish gate — darwin Keychain backend present | |
| run: | | |
| set -euo pipefail | |
| art=dist/artifacts.json | |
| arm_bin=$(jq -r '.[]|select(.type=="Binary" and .goos=="darwin" and .goarch=="arm64")|.path' "$art") | |
| amd_bin=$(jq -r '.[]|select(.type=="Binary" and .goos=="darwin" and .goarch=="amd64")|.path' "$art") | |
| [ -n "$arm_bin" ] && [ -n "$amd_bin" ] || { echo "missing a darwin binary in artifacts.json"; exit 1; } | |
| # darwin archives: exactly one per arch, no duplicate names | |
| tot=$(jq '[.[]|select(.type=="Archive" and .goos=="darwin")|.name]|length' "$art") | |
| uniq=$(jq '[.[]|select(.type=="Archive" and .goos=="darwin")|.name]|unique|length' "$art") | |
| [ "$tot" = "$uniq" ] || { echo "duplicate darwin archive names"; exit 1; } | |
| [ "$(jq '[.[]|select(.type=="Archive" and .goos=="darwin" and .goarch=="arm64")]|length' "$art")" = 1 ] || { echo "expected exactly one darwin/arm64 archive"; exit 1; } | |
| [ "$(jq '[.[]|select(.type=="Archive" and .goos=="darwin" and .goarch=="amd64")]|length' "$art")" = 1 ] || { echo "expected exactly one darwin/amd64 archive"; exit 1; } | |
| # Mach-O arch sanity (both slices) | |
| file "$arm_bin" | grep -q 'arm64' || { echo "arm64 binary is not arm64 Mach-O"; exit 1; } | |
| file "$amd_bin" | grep -q 'x86_64' || { echo "amd64 binary is not x86_64 Mach-O"; exit 1; } | |
| lipo -archs "$arm_bin" | grep -qw arm64 || { echo "lipo: arm64 slice missing"; exit 1; } | |
| lipo -archs "$amd_bin" | grep -qw x86_64 || { echo "lipo: x86_64 slice missing"; exit 1; } | |
| # amd64 cannot run on the arm64 runner: assert Security.framework | |
| # is linked. CGO_ENABLED=0 omits it entirely, so its presence is a | |
| # sound *necessary* cgo signal for the slice we can't execute. | |
| otool -L "$amd_bin" | grep -q '/System/Library/Frameworks/Security.framework' \ | |
| || { echo "amd64 binary not linked against Security.framework (cgo missing)"; exit 1; } | |
| # arm64 authoritative functional check: with no backend override | |
| # and a seeded config, credstore must auto-select the Keychain. | |
| # config.yml lives under $XDG_CONFIG_HOME/google-readonly/config.yml. | |
| # -u GOOGLE_READONLY_KEYRING_BACKEND: derived from DirName | |
| # "google-readonly" upper-snake-cased. | |
| tmp=$(mktemp -d) | |
| mkdir -p "$tmp/xdg/google-readonly" | |
| printf 'credential_ref: google-readonly/default\n' > "$tmp/xdg/google-readonly/config.yml" | |
| out=$(env -u GOOGLE_READONLY_KEYRING_BACKEND HOME="$tmp" XDG_CONFIG_HOME="$tmp/xdg" "$arm_bin" config show -j) | |
| echo "$out" | |
| b=$(echo "$out" | jq -r '.backend'); s=$(echo "$out" | jq -r '.backend_source'); r=$(echo "$out" | jq -r '.credential_ref') | |
| [ "$b" = "keychain" ] && [ "$s" = "auto" ] && [ "$r" = "google-readonly/default" ] \ | |
| || { echo "GATE FAIL: backend=$b source=$s ref=$r (want keychain/auto/google-readonly/default)"; exit 1; } | |
| echo "GATE OK: darwin/arm64 backend=keychain source=auto; darwin/amd64 Security.framework linked" | |
| - name: Release notes | |
| run: | | |
| set -euo pipefail | |
| cat > "$RUNNER_TEMP/release-notes.md" <<'EOF' | |
| ### macOS Keychain storage restored | |
| Builds since the credential-store migration were compiled without | |
| cgo and failed closed on macOS (no Keychain backend). This release | |
| builds the darwin binaries with cgo enabled, restoring native | |
| macOS Keychain storage. Upgrade and re-run your normal commands; | |
| no other action is required. | |
| EOF | |
| - name: Release (publish) | |
| run: goreleaser release --clean --release-notes="$RUNNER_TEMP/release-notes.md" | |
| env: | |
| # TAP_GITHUB_TOKEN (PAT) is required here instead of the default | |
| # GITHUB_TOKEN because releases created with GITHUB_TOKEN do not fire | |
| # downstream workflow triggers (release: published). Using the PAT | |
| # lets chocolatey-publish.yml and winget-publish.yml auto-trigger. | |
| GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} | |
| TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} | |
| - name: Verify release notes published | |
| env: | |
| GH_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| body=$(gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json body -q .body) | |
| if ! printf '%s' "$body" | grep -q 'macOS Keychain'; then | |
| gh release edit "$TAG" --repo "$GITHUB_REPOSITORY" --notes-file "$RUNNER_TEMP/release-notes.md" | |
| fi | |
| # Snap is temporarily disabled — waiting for personal-files interface approval. | |
| snap: | |
| if: false | |
| needs: goreleaser | |
| runs-on: ubuntu-latest | |
| env: | |
| TAG: ${{ github.ref_name || inputs.tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ env.TAG }} | |
| fetch-depth: 0 | |
| - name: Set snap version from tag | |
| run: | | |
| VERSION="${TAG#v}" | |
| sed -i "s/^version: git$/version: '${VERSION}'/" snap/snapcraft.yaml | |
| echo "Snap version: ${VERSION}" | |
| grep '^version:' snap/snapcraft.yaml | |
| - name: Build snap | |
| uses: snapcore/action-build@v1 | |
| id: build | |
| - name: Publish to Snapcraft Store | |
| uses: snapcore/action-publish@v1 | |
| env: | |
| SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} | |
| with: | |
| snap: ${{ steps.build.outputs.snap }} | |
| release: stable | |
| linux-packages: | |
| needs: goreleaser | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - name: Trigger linux-packages repo update | |
| uses: peter-evans/repository-dispatch@v3 | |
| with: | |
| token: ${{ secrets.LINUX_PACKAGES_DISPATCH_TOKEN }} | |
| repository: open-cli-collective/linux-packages | |
| event-type: package-release | |
| client-payload: |- | |
| { | |
| "package": "google-readonly", | |
| "version": "${{ github.ref_name }}", | |
| "repo": "open-cli-collective/google-readonly" | |
| } |