fix: stale oauth tokens invalidate setup instead of forcing re-auth #543
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-canary | |
| on: | |
| push: | |
| branches: | |
| - "**" | |
| workflow_dispatch: | |
| concurrency: | |
| group: release-canary-${{ github.ref_name }} | |
| cancel-in-progress: true | |
| permissions: | |
| actions: read | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| env: | |
| CARGO_NET_GIT_FETCH_WITH_CLI: true | |
| jobs: | |
| plan: | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| val: ${{ steps.plan.outputs.manifest }} | |
| short-sha: ${{ steps.meta.outputs.short_sha }} | |
| branch-slug: ${{ steps.meta.outputs.branch_slug }} | |
| canary-tag: ${{ steps.meta.outputs.canary_tag }} | |
| alias-tag: ${{ steps.meta.outputs.alias_tag }} | |
| dist-tag: ${{ steps.meta.outputs.dist_tag }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| submodules: recursive | |
| - name: Configure git auth for private dependencies | |
| shell: bash | |
| run: | | |
| token="${BT_GITHUB_TOKEN:-$GITHUB_TOKEN}" | |
| git config --global url."https://x-access-token:${token}@github.com/".insteadOf "https://github.com/" | |
| env: | |
| BT_GITHUB_TOKEN: ${{ secrets.BT_GITHUB_TOKEN }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install dist | |
| shell: bash | |
| run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.30.3/cargo-dist-installer.sh | sh" | |
| - name: Cache dist | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: cargo-dist-cache | |
| path: ~/.cargo/bin/dist | |
| - id: meta | |
| shell: bash | |
| run: | | |
| branch_slug="$(echo "${GITHUB_REF_NAME}" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g' | cut -c1-40)" | |
| if [ -z "$branch_slug" ]; then | |
| branch_slug="branch" | |
| fi | |
| short_sha="${GITHUB_SHA::12}" | |
| pkg_version="$(grep -m1 '^version = "' Cargo.toml | cut -d '"' -f2)" | |
| if [ -z "$pkg_version" ]; then | |
| echo "Failed to determine package version from Cargo.toml" >&2 | |
| exit 1 | |
| fi | |
| if [ "${GITHUB_REF_NAME}" = "main" ]; then | |
| canary_tag="canary-$short_sha" | |
| alias_tag="canary" | |
| else | |
| canary_tag="canary-${branch_slug}-$short_sha" | |
| alias_tag="canary-${branch_slug}" | |
| fi | |
| dist_tag="v${pkg_version}" | |
| echo "short_sha=$short_sha" >> "$GITHUB_OUTPUT" | |
| echo "branch_slug=$branch_slug" >> "$GITHUB_OUTPUT" | |
| echo "canary_tag=$canary_tag" >> "$GITHUB_OUTPUT" | |
| echo "alias_tag=$alias_tag" >> "$GITHUB_OUTPUT" | |
| echo "dist_tag=$dist_tag" >> "$GITHUB_OUTPUT" | |
| - id: plan | |
| shell: bash | |
| run: | | |
| dist host --steps=create --tag="${{ steps.meta.outputs.dist_tag }}" --output-format=json > plan-dist-manifest.json | |
| echo "dist ran successfully" | |
| cat plan-dist-manifest.json | |
| echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" | |
| - name: Upload dist plan manifest | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: artifacts-plan-dist-manifest | |
| path: plan-dist-manifest.json | |
| build-local-artifacts: | |
| name: build-local-artifacts (${{ join(matrix.targets, ', ') }}) | |
| needs: | |
| - plan | |
| if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null }} | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} | |
| runs-on: ${{ matrix.runner }} | |
| container: ${{ matrix.container && matrix.container.image || null }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json | |
| steps: | |
| - name: Enable windows longpaths | |
| run: git config --global core.longpaths true | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| submodules: recursive | |
| - name: Configure git auth for private dependencies | |
| shell: bash | |
| run: | | |
| token="${BT_GITHUB_TOKEN:-$GITHUB_TOKEN}" | |
| git config --global url."https://x-access-token:${token}@github.com/".insteadOf "https://github.com/" | |
| env: | |
| BT_GITHUB_TOKEN: ${{ secrets.BT_GITHUB_TOKEN }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install Rust non-interactively if not already installed | |
| if: ${{ matrix.container }} | |
| run: | | |
| if ! command -v cargo > /dev/null 2>&1; then | |
| curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y | |
| echo "$HOME/.cargo/bin" >> $GITHUB_PATH | |
| fi | |
| - name: Install dist | |
| run: ${{ matrix.install_dist.run }} | |
| - name: Fetch local artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| pattern: artifacts-* | |
| path: target/distrib/ | |
| merge-multiple: true | |
| - name: Install dependencies | |
| run: ${{ matrix.packages_install }} | |
| - name: Build artifacts | |
| shell: bash | |
| run: | | |
| dist build --tag="${{ needs.plan.outputs.dist-tag }}" --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json | |
| echo "dist ran successfully" | |
| - id: dist-files | |
| name: Post-build | |
| shell: bash | |
| run: | | |
| echo "paths<<EOF" >> "$GITHUB_OUTPUT" | |
| dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| cp dist-manifest.json "$BUILD_MANIFEST_NAME" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: artifacts-build-local-${{ join(matrix.targets, '_') }} | |
| path: | | |
| ${{ steps.dist-files.outputs.paths }} | |
| ${{ env.BUILD_MANIFEST_NAME }} | |
| build-global-artifacts: | |
| needs: | |
| - plan | |
| - build-local-artifacts | |
| runs-on: ubuntu-22.04 | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| submodules: recursive | |
| - name: Configure git auth for private dependencies | |
| shell: bash | |
| run: | | |
| token="${BT_GITHUB_TOKEN:-$GITHUB_TOKEN}" | |
| git config --global url."https://x-access-token:${token}@github.com/".insteadOf "https://github.com/" | |
| env: | |
| BT_GITHUB_TOKEN: ${{ secrets.BT_GITHUB_TOKEN }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install cached dist | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: cargo-dist-cache | |
| path: ~/.cargo/bin/ | |
| - run: chmod +x ~/.cargo/bin/dist | |
| - name: Fetch local artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| pattern: artifacts-* | |
| path: target/distrib/ | |
| merge-multiple: true | |
| - id: dist-files | |
| shell: bash | |
| run: | | |
| dist build --tag="${{ needs.plan.outputs.dist-tag }}" --output-format=json --artifacts=global > dist-manifest.json | |
| echo "dist ran successfully" | |
| echo "paths<<EOF" >> "$GITHUB_OUTPUT" | |
| dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| cp dist-manifest.json "$BUILD_MANIFEST_NAME" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: artifacts-build-global | |
| path: | | |
| ${{ steps.dist-files.outputs.paths }} | |
| ${{ env.BUILD_MANIFEST_NAME }} | |
| announce: | |
| needs: | |
| - plan | |
| - build-local-artifacts | |
| - build-global-artifacts | |
| if: ${{ (github.ref_name == 'main' || github.event_name == 'workflow_dispatch') && always() && needs.plan.result == 'success' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} | |
| runs-on: ubuntu-22.04 | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| CANARY_TAG: ${{ needs.plan.outputs.canary-tag }} | |
| ALIAS_TAG: ${{ needs.plan.outputs.alias-tag }} | |
| DIST_TAG: ${{ needs.plan.outputs.dist-tag }} | |
| SHORT_SHA: ${{ needs.plan.outputs.short-sha }} | |
| BRANCH_NAME: ${{ github.ref_name }} | |
| REPO: ${{ github.repository }} | |
| steps: | |
| - name: Download GitHub artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| pattern: artifacts-* | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Cleanup | |
| run: rm -f artifacts/*-dist-manifest.json | |
| - name: Publish immutable canary release | |
| shell: bash | |
| run: | | |
| for installer in artifacts/bt-installer.sh artifacts/bt-installer.ps1; do | |
| if [ -f "$installer" ]; then | |
| sed -i \ | |
| -e "s|/releases/download/${DIST_TAG}/|/releases/download/${CANARY_TAG}/|g" \ | |
| -e "s|/releases/download/${DIST_TAG}|/releases/download/${CANARY_TAG}|g" \ | |
| -e "s|${DIST_TAG}|${CANARY_TAG}|g" \ | |
| "$installer" | |
| fi | |
| done | |
| cat > "$RUNNER_TEMP/canary-notes.md" <<EOF | |
| Canary build from branch \`${BRANCH_NAME}\` at commit \`${GITHUB_SHA}\`. | |
| Install this exact build: | |
| - Unix: \`curl -fsSL https://github.com/${REPO}/releases/download/${CANARY_TAG}/bt-installer.sh | sh\` | |
| - Windows: \`powershell -ExecutionPolicy Bypass -c "irm https://github.com/${REPO}/releases/download/${CANARY_TAG}/bt-installer.ps1 | iex"\` | |
| EOF | |
| if gh release view "$CANARY_TAG" --repo "$REPO" >/dev/null 2>&1; then | |
| gh release delete "$CANARY_TAG" --repo "$REPO" --yes --cleanup-tag | |
| fi | |
| gh release create "$CANARY_TAG" \ | |
| --repo "$REPO" \ | |
| --target "${GITHUB_SHA}" \ | |
| --title "Canary ${SHORT_SHA}" \ | |
| --prerelease \ | |
| --notes-file "$RUNNER_TEMP/canary-notes.md" \ | |
| artifacts/* | |
| - name: Publish moving canary alias (latest branch head only) | |
| shell: bash | |
| run: | | |
| encoded_ref="$(printf '%s' "${BRANCH_NAME}" | jq -sRr @uri)" | |
| latest_branch_sha="$(gh api "repos/${REPO}/git/ref/heads/${encoded_ref}" --jq .object.sha)" | |
| if [ "$latest_branch_sha" != "${GITHUB_SHA}" ]; then | |
| echo "Skipping moving canary alias for non-latest ${BRANCH_NAME} commit: ${GITHUB_SHA}" | |
| exit 0 | |
| fi | |
| for installer in artifacts/bt-installer.sh artifacts/bt-installer.ps1; do | |
| if [ -f "$installer" ]; then | |
| sed -i \ | |
| -e "s|/releases/download/${CANARY_TAG}/|/releases/download/${ALIAS_TAG}/|g" \ | |
| -e "s|/releases/download/${CANARY_TAG}|/releases/download/${ALIAS_TAG}|g" \ | |
| -e "s|/releases/download/${DIST_TAG}/|/releases/download/${ALIAS_TAG}/|g" \ | |
| -e "s|/releases/download/${DIST_TAG}|/releases/download/${ALIAS_TAG}|g" \ | |
| -e "s|${CANARY_TAG}|${ALIAS_TAG}|g" \ | |
| -e "s|${DIST_TAG}|${ALIAS_TAG}|g" \ | |
| "$installer" | |
| fi | |
| done | |
| cat > "$RUNNER_TEMP/canary-latest-notes.md" <<EOF | |
| Latest canary build from branch \`${BRANCH_NAME}\` at commit \`${GITHUB_SHA}\`. | |
| Install latest branch canary: | |
| - Unix: \`curl -fsSL https://github.com/${REPO}/releases/download/${ALIAS_TAG}/bt-installer.sh | sh\` | |
| - Windows: \`powershell -ExecutionPolicy Bypass -c "irm https://github.com/${REPO}/releases/download/${ALIAS_TAG}/bt-installer.ps1 | iex"\` | |
| EOF | |
| if gh release view "$ALIAS_TAG" --repo "$REPO" >/dev/null 2>&1; then | |
| gh release delete "$ALIAS_TAG" --repo "$REPO" --yes --cleanup-tag | |
| fi | |
| gh release create "$ALIAS_TAG" \ | |
| --repo "$REPO" \ | |
| --target "${GITHUB_SHA}" \ | |
| --title "Canary (latest ${BRANCH_NAME})" \ | |
| --prerelease \ | |
| --notes-file "$RUNNER_TEMP/canary-latest-notes.md" \ | |
| artifacts/* | |
| - name: Print install commands | |
| shell: bash | |
| run: | | |
| exact_unix="curl -fsSL https://github.com/${REPO}/releases/download/${CANARY_TAG}/bt-installer.sh | sh" | |
| exact_windows="powershell -ExecutionPolicy Bypass -c \"irm https://github.com/${REPO}/releases/download/${CANARY_TAG}/bt-installer.ps1 | iex\"" | |
| latest_unix="curl -fsSL https://github.com/${REPO}/releases/download/${ALIAS_TAG}/bt-installer.sh | sh" | |
| latest_windows="powershell -ExecutionPolicy Bypass -c \"irm https://github.com/${REPO}/releases/download/${ALIAS_TAG}/bt-installer.ps1 | iex\"" | |
| echo "Install exact build (Unix): $exact_unix" | |
| echo "Install exact build (Windows): $exact_windows" | |
| echo "Install latest branch canary (Unix): $latest_unix" | |
| echo "Install latest branch canary (Windows): $latest_windows" | |
| { | |
| echo "## Canary Install Commands" | |
| echo "" | |
| echo "Branch: \`${BRANCH_NAME}\`" | |
| echo "Commit: \`${GITHUB_SHA}\`" | |
| echo "Exact tag: \`${CANARY_TAG}\`" | |
| echo "Latest branch tag: \`${ALIAS_TAG}\`" | |
| echo "" | |
| echo "Exact build (Unix):" | |
| echo '```bash' | |
| echo "$exact_unix" | |
| echo '```' | |
| echo "" | |
| echo "Latest branch canary (Unix):" | |
| echo '```bash' | |
| echo "$latest_unix" | |
| echo '```' | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| comment-pr-install: | |
| needs: | |
| - plan | |
| - build-local-artifacts | |
| - build-global-artifacts | |
| if: ${{ github.event_name == 'push' && github.ref_name != 'main' && always() && needs.plan.result == 'success' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} | |
| runs-on: ubuntu-22.04 | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| OWNER: ${{ github.repository_owner }} | |
| BRANCH_NAME: ${{ github.ref_name }} | |
| SHORT_SHA: ${{ needs.plan.outputs.short-sha }} | |
| RUN_ID: ${{ github.run_id }} | |
| steps: | |
| - name: Upsert PR install comment | |
| shell: bash | |
| run: | | |
| encoded_head="$(printf '%s' "${OWNER}:${BRANCH_NAME}" | jq -sRr @uri)" | |
| pr_number="$(gh api --method GET "repos/${REPO}/pulls?state=open&head=${encoded_head}" --jq '.[0].number // empty')" | |
| if [ -z "$pr_number" ]; then | |
| echo "No open PR found for ${OWNER}:${BRANCH_NAME}; skipping PR install comment." | |
| exit 0 | |
| fi | |
| marker="<!-- bt-pr-canary-install-comment -->" | |
| run_url="https://github.com/${REPO}/actions/runs/${RUN_ID}" | |
| artifacts="$(gh api --method GET "repos/${REPO}/actions/runs/${RUN_ID}/artifacts?per_page=100" | jq -r '.artifacts[] | select(.expired == false) | .name' | sed 's/^/- `&`/' || true)" | |
| if [ -z "$artifacts" ]; then | |
| artifacts="- (no artifacts found)" | |
| fi | |
| body_file="$RUNNER_TEMP/pr-canary-install-comment.md" | |
| { | |
| cat <<EOF | |
| ${marker} | |
| Latest downloadable build artifacts for this PR commit \`${SHORT_SHA}\`: | |
| - Workflow run: ${run_url} | |
| - Download all artifacts (GitHub CLI): \`gh run download ${RUN_ID} --repo ${REPO}\` | |
| - Installers are published from \`main\` automatically. To publish one for a PR branch, run \`release-canary\` manually via \`workflow_dispatch\`. | |
| <details> | |
| <summary>Available artifact names</summary> | |
| EOF | |
| printf '%s\n' "$artifacts" | |
| cat <<EOF | |
| </details> | |
| EOF | |
| } > "$body_file" | |
| payload_file="$RUNNER_TEMP/pr-comment-payload.json" | |
| jq -n --arg body "$(cat "$body_file")" '{body:$body}' > "$payload_file" | |
| comment_id="$(gh api --method GET "repos/${REPO}/issues/${pr_number}/comments" --paginate --jq ".[] | select(.body | contains(\"${marker}\")) | .id" | head -n1)" | |
| if [ -n "$comment_id" ]; then | |
| gh api --method PATCH "repos/${REPO}/issues/comments/${comment_id}" --input "$payload_file" >/dev/null | |
| echo "Updated PR #${pr_number} install comment (${comment_id})." | |
| else | |
| gh api --method POST "repos/${REPO}/issues/${pr_number}/comments" --input "$payload_file" >/dev/null | |
| echo "Created PR #${pr_number} install comment." | |
| fi | |
| smoke-install-unix: | |
| needs: | |
| - plan | |
| - announce | |
| if: ${{ needs.announce.result == 'success' }} | |
| runs-on: ubuntu-22.04 | |
| env: | |
| CANARY_TAG: ${{ needs.plan.outputs.canary-tag }} | |
| REPO: ${{ github.repository }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| steps: | |
| - name: Install from immutable canary installer | |
| shell: bash | |
| run: | | |
| curl -fsSL "https://github.com/${REPO}/releases/download/${CANARY_TAG}/bt-installer.sh" | sh | |
| - name: Verify installed binary | |
| shell: bash | |
| run: | | |
| export PATH="${XDG_BIN_HOME:-$HOME/.local/bin}:$PATH" | |
| bt --version | grep -i canary | |
| bt self update --check | |
| smoke-install-macos: | |
| needs: | |
| - plan | |
| - announce | |
| if: ${{ needs.announce.result == 'success' && vars.BT_ENABLE_MACOS_SMOKE == '1' }} | |
| runs-on: macos-13 | |
| env: | |
| CANARY_TAG: ${{ needs.plan.outputs.canary-tag }} | |
| REPO: ${{ github.repository }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| steps: | |
| - name: Install from immutable canary installer | |
| shell: bash | |
| run: | | |
| curl -fsSL "https://github.com/${REPO}/releases/download/${CANARY_TAG}/bt-installer.sh" | sh | |
| - name: Verify installed binary | |
| shell: bash | |
| run: | | |
| export PATH="${XDG_BIN_HOME:-$HOME/.local/bin}:$PATH" | |
| bt --version | grep -i canary | |
| bt self update --check | |
| smoke-install-windows: | |
| needs: | |
| - plan | |
| - announce | |
| if: ${{ needs.announce.result == 'success' }} | |
| runs-on: windows-2022 | |
| env: | |
| CANARY_TAG: ${{ needs.plan.outputs.canary-tag }} | |
| REPO: ${{ github.repository }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| steps: | |
| - name: Install from immutable canary installer | |
| shell: pwsh | |
| run: | | |
| irm "https://github.com/${env:REPO}/releases/download/${env:CANARY_TAG}/bt-installer.ps1" | iex | |
| - name: Verify installed binary | |
| shell: pwsh | |
| run: | | |
| $binDir = if ($env:XDG_BIN_HOME) { $env:XDG_BIN_HOME } else { Join-Path $HOME ".local/bin" } | |
| $btExe = Join-Path $binDir "bt.exe" | |
| if (!(Test-Path $btExe)) { | |
| throw "bt.exe not found at $btExe" | |
| } | |
| $version = & $btExe --version | |
| if ($version -notmatch "canary") { | |
| throw "expected canary version string, got: $version" | |
| } | |
| $env:PATH = "$binDir;$env:PATH" | |
| & $btExe self update --check |