Skip to content

chore(master): release 0.18.2 (#383) #35

chore(master): release 0.18.2 (#383)

chore(master): release 0.18.2 (#383) #35

Workflow file for this run

# Desktop release: build signed artifacts (build-desktop.yml, sign: true), upload the
# electron-updater feed to Cloudflare R2 (served at https://releases.linkcode.ai/desktop), then
# publish a GitHub Release for human downloads — the updater never reads it.
# Normally triggered by Finalize Releases pushing a release-please v*.*.* tag after CI succeeds;
# workflow_dispatch remains available for a signed dry run.
name: Release Desktop
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
ref:
description: Git ref (tag / branch / SHA) to release
type: string
required: true
dry_run:
description: Build + sign but DO NOT publish a release
type: boolean
default: true
concurrency:
group: release-desktop-${{ github.ref }}
cancel-in-progress: false # never cancel a release mid-flight
permissions:
contents: read
jobs:
build:
name: Build signed artifacts
uses: ./.github/workflows/build-desktop.yml
secrets: inherit # required so build-desktop.yml can read the signing secrets
permissions:
contents: read
id-token: write # the called workflow mints an OIDC token for azure/login (Trusted Signing)
with:
ref: ${{ inputs.ref || github.ref }}
sign: true
release:
name: Publish release
needs: build
runs-on: ${{ vars.CI_RUNNER_LINUX || 'ubuntu-latest' }}
# R2 credentials live in the `release` environment (same gate as the signing secrets) —
# without this reference the job resolves them as empty.
environment: release
permissions:
contents: write # required to create the GitHub Release
env:
R2_BUCKET: linkcode-releases
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
# Gate for the Homebrew and WinGet bumps (below). Either secret absent ⇒ they self-skip.
BOT_APP_ID: ${{ secrets.BOT_APP_ID }}
BOT_APP_PRIVATE_KEY: ${{ secrets.BOT_APP_PRIVATE_KEY }}
steps:
- parallel:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ inputs.ref || github.ref }}
persist-credentials: false
- name: Download all build artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: desktop-*
merge-multiple: true
path: artifacts
- name: Resolve tag
id: meta
run: |
if [ "${{ github.event_name }}" = "push" ]; then
echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
else
echo "tag=${{ inputs.ref }}" >> "$GITHUB_OUTPUT"
fi
- name: Verify release-please Release exists
if: ${{ github.event_name == 'push' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
TAG: ${{ steps.meta.outputs.tag }}
RELEASE_SHA: ${{ github.sha }}
with:
github-token: ${{ github.token }}
script: |
const automation = require('./.github/scripts/release-automation.cjs')
await automation.verifyDesktopRelease({
github,
...context.repo,
sha: process.env.RELEASE_SHA,
tag: process.env.TAG,
})
# Upload both copies concurrently, but keep the GitHub Release as a draft until the R2
# updater feed and every GitHub asset have finished successfully.
- parallel:
- name: Publish update feed to R2
# The live updater feed (installers + latest*.yml + *.blockmap), public via
# https://releases.linkcode.ai — the publish.url baked into shipped apps.
# No --delete: prior versions stay for delta updates.
if: ${{ github.event_name == 'push' || inputs.dry_run == false }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_REGION: auto # R2 ignores region, but the CLI requires one to be set
# R2 doesn't implement the CRC32 upload checksums that recent aws-cli sends by default.
AWS_REQUEST_CHECKSUM_CALCULATION: WHEN_REQUIRED
AWS_RESPONSE_CHECKSUM_VALIDATION: WHEN_REQUIRED
run: |
aws s3 sync artifacts/ "s3://${R2_BUCKET}/desktop/" \
--endpoint-url "https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com" \
--no-progress \
--exclude "*" \
--include "*.dmg" --include "*.zip" --include "*.exe" --include "*.msi" \
--include "*.appx" --include "*.AppImage" --include "*.deb" --include "*.rpm" \
--include "*.snap" --include "*.yml" --include "*.blockmap"
- name: Upload GitHub Release assets
id: release-assets
if: ${{ github.event_name == 'push' || inputs.dry_run == false }}
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ steps.meta.outputs.tag }}
# release-please creates this draft before the tag push. Keep it private while the
# assets upload; the next step publishes this exact release after the parallel wait.
draft: true
prerelease: ${{ contains(steps.meta.outputs.tag, '-') }} # v1.2.3-beta.1 => prerelease
files: |
artifacts/*.dmg
artifacts/*.zip
artifacts/*.exe
artifacts/*.msi
artifacts/*.appx
artifacts/*.AppImage
artifacts/*.deb
artifacts/*.rpm
artifacts/*.snap
artifacts/*.yml
artifacts/*.blockmap
- name: Publish GitHub Release
if: ${{ github.event_name == 'push' || inputs.dry_run == false }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
RELEASE_ID: ${{ steps.release-assets.outputs.id }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.repos.updateRelease({
...context.repo,
release_id: Number(process.env.RELEASE_ID),
draft: false,
})
- name: Mint Homebrew tap token
# Keep the LinkCode cask in arcboxlabs/homebrew-tap in step with releases so
# `brew upgrade --cask arcboxlabs/tap/linkcode` tracks the latest version. Auth mirrors
# arcbox's release flow: the org GitHub App (BOT_APP_ID / BOT_APP_PRIVATE_KEY) mints a
# short-lived token scoped to the tap repo. Release version tags only: `startsWith(…, 'v')`
# keeps a manual dispatch of a branch/SHA from bumping the cask to a non-version (the
# artifact names are `LinkCode-<semver>-<arch>.dmg`), and `!contains(…, '-')` keeps a
# prerelease tag (v*.*.*-…) from moving the stable cask. Self-skips when either App secret
# is absent (later steps gate on the empty token output) so a release still succeeds.
# The tap edit itself lives in arcboxlabs/homebrew-tap/.github/actions/bump-cask.
id: tap-token
if: ${{ (github.event_name == 'push' || inputs.dry_run == false) && startsWith(steps.meta.outputs.tag, 'v') && !contains(steps.meta.outputs.tag, '-') && env.BOT_APP_ID != '' && env.BOT_APP_PRIVATE_KEY != '' }}
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
with:
app-id: ${{ secrets.BOT_APP_ID }}
private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: homebrew-tap
- name: Hash LinkCode DMGs
if: ${{ steps.tap-token.outputs.token != '' }}
id: cask-shas
env:
TAG: ${{ steps.meta.outputs.tag }}
run: |
set -euo pipefail
version="${TAG#v}"
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "arm=$(sha256sum "artifacts/LinkCode-${version}-arm64.dmg" | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
echo "intel=$(sha256sum "artifacts/LinkCode-${version}-x64.dmg" | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
- name: Bump Homebrew cask
if: ${{ steps.tap-token.outputs.token != '' }}
uses: arcboxlabs/homebrew-tap/.github/actions/bump-cask@19f97aa3ca8a15c3fdbbf018c1b79651bfdebb8d
with:
token: ${{ steps.tap-token.outputs.token }}
cask: linkcode
version: ${{ steps.cask-shas.outputs.version }}
arm_sha256: ${{ steps.cask-shas.outputs.arm }}
intel_sha256: ${{ steps.cask-shas.outputs.intel }}
- name: Mint WinGet fork token
# The App must be installed on the org fork arcboxlabs/winget-pkgs (contents +
# pull-requests write); komac pushes its branch there before opening the upstream PR.
id: winget-token
if: ${{ (github.event_name == 'push' || inputs.dry_run == false) && startsWith(steps.meta.outputs.tag, 'v') && !contains(steps.meta.outputs.tag, '-') && env.BOT_APP_ID != '' && env.BOT_APP_PRIVATE_KEY != '' }}
continue-on-error: true
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
with:
app-id: ${{ secrets.BOT_APP_ID }}
private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: winget-pkgs
- name: Publish to WinGet
# Soft-fail on purpose: the action only *updates* a package already in winget-pkgs, and an
# App installation token may be refused when opening the PR on microsoft/winget-pkgs.
if: ${{ steps.winget-token.outputs.token != '' }}
continue-on-error: true
uses: vedantmgoyal9/winget-releaser@4ffc7888bffd451b357355dc214d43bb9f23917e # v2
with:
identifier: ArcBox.LinkCode
release-tag: ${{ steps.meta.outputs.tag }}
installers-regex: '\.exe$'
token: ${{ steps.winget-token.outputs.token }}
fork-user: ${{ github.repository_owner }}
- name: Dry-run summary
if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run == true }}
run: |
{
echo "### Dry run — nothing published"
echo ""
echo "Artifacts that *would* be released for \`${{ steps.meta.outputs.tag }}\`:"
echo '```'
ls -1 artifacts
echo '```'
} >> "$GITHUB_STEP_SUMMARY"