Skip to content

fix: stale oauth tokens invalidate setup instead of forcing re-auth #543

fix: stale oauth tokens invalidate setup instead of forcing re-auth

fix: stale oauth tokens invalidate setup instead of forcing re-auth #543

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