Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/local-workflows.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Fork-local files — protected during upstream sync.
#
# Used by .github/workflows/sync-upstream.yml: when a scheduled upstream
# merge conflicts on a file listed here, the fork's version wins
# automatically ("ours"); conflicts in any other file stop the sync for
# manual resolution. One path per line, relative to repo root. Comments (#)
# and blank lines are ignored.
#
# These entries are insurance, not divergence: each file below carries the
# opt-in release-ops pipeline (Apple code signing, notarization, Homebrew
# tap publishing, fork sync) in a form offered upstream verbatim, following
# the fork-friendly release-ops design from the jira-cli project,
# documented at (commit-pinned)
# https://github.com/ArcavenAE/jira-cli/blob/f85647bdef1bf77f85ce1440dcfd9b9dd0413093/docs/specs/fork-friendly-release-ops.md
# While the two copies are identical, no conflict can occur; entries can be
# pruned as upstream adopts them. This file lists itself so the fork's list survives upstream
# template changes.
.github/local-workflows.txt
.github/workflows/sign-and-publish.yml
.github/workflows/sync-upstream.yml
.github/workflows/backfill-release.yml
.github/workflows/signing-guard.yml
Formula/wirerust.rb
Formula/wirerust-a.rb
Formula/wirerust-b.rb
Formula/wirerust-d.rb
Formula/wirerust-rc.rb
packaging/Info.plist
scripts/create-app.sh
scripts/create-dmg.sh
scripts/create-pkg.sh
scripts/check-signing-workflow-injection.sh
scripts/sign-and-notarize.sh
scripts/update-homebrew-formula.sh
334 changes: 334 additions & 0 deletions .github/workflows/backfill-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
# Backfill Release — build, release, sign, and publish for an existing tag.
#
# Use this to create full releases for tags that predate release.yml (or the
# signing pipeline). Trigger once per tag via workflow_dispatch, or let
# release-gap-fill.yml dispatch it automatically.
#
# OPT-IN signing: the sign and homebrew jobs are gated on repository
# variables (SIGNING_ENABLED, HOMEBREW_TAP_REPO) and skip cleanly when
# unset. Without them this workflow still backfills unsigned releases.
# External design doc (commit-pinned):
# https://github.com/ArcavenAE/jira-cli/blob/f85647bdef1bf77f85ce1440dcfd9b9dd0413093/docs/specs/fork-friendly-release-ops.md
name: Backfill Release

on:
workflow_dispatch:
inputs:
tag:
description: 'Git tag to build and release (e.g. v0.3.0)'
required: true
type: string
skip_signing:
description: 'Skip signing and just create the unsigned release'
required: false
type: boolean
default: false
update_homebrew:
description: 'Update Homebrew tap formula (only for latest stable)'
required: false
type: boolean
default: false

permissions:
contents: read

jobs:
# ---------------------------------------------------------------------------
# Build — same targets as release.yml
# ---------------------------------------------------------------------------
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
matrix:
include:
- target: x86_64-apple-darwin
os: macos-latest
- target: aarch64-apple-darwin
os: macos-latest
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
- target: x86_64-pc-windows-msvc
os: windows-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ inputs.tag }}
persist-credentials: false

- name: Install Rust
# Pinned to master, which accepts an explicit `toolchain` input. The
# SHA-pinned versioned-branch snapshot used in jira-cli hardcodes its
# toolchain (1.85.0) and ignores the input; jira-cli gets away with it
# because its rust-toolchain.toml pins channel = stable, but wirerust
# carries no rust-toolchain.toml (requires rustc 1.91+).
uses: dtolnay/rust-toolchain@2c7215f132e9ebf062739d9130488b56d53c060c # master, 2026-07-16; matches open PR #451
with:
toolchain: stable
targets: ${{ matrix.target }}

# rust-toolchain.toml pins channel = "stable", which overrides the
# toolchain dtolnay/rust-toolchain installs above. Without this step,
# native (non-cross) builds fail with `error[E0463]: can't find
# crate for 'core'`. Same defensive fix as release.yml.
- name: Ensure target installed (defensive)
shell: bash
run: rustup target add ${{ matrix.target }}

- name: Build
shell: bash
run: cargo build --release --target ${{ matrix.target }}

- name: Package
if: runner.os != 'Windows'
shell: bash
env:
RELEASE_TAG: ${{ inputs.tag }}
run: |
cd target/${{ matrix.target }}/release
tar czf "../../../wirerust-${RELEASE_TAG}-${{ matrix.target }}.tar.gz" wirerust
cd ../../..
if command -v sha256sum &>/dev/null; then
sha256sum "wirerust-${RELEASE_TAG}-${{ matrix.target }}.tar.gz" > "wirerust-${RELEASE_TAG}-${{ matrix.target }}.tar.gz.sha256"
else
shasum -a 256 "wirerust-${RELEASE_TAG}-${{ matrix.target }}.tar.gz" > "wirerust-${RELEASE_TAG}-${{ matrix.target }}.tar.gz.sha256"
fi

- name: Package (Windows)
if: runner.os == 'Windows'
shell: pwsh
env:
RELEASE_TAG: ${{ inputs.tag }}
run: Compress-Archive -Path "target/${{ matrix.target }}/release/wirerust.exe" -DestinationPath "wirerust-${env:RELEASE_TAG}-${{ matrix.target }}.zip"

- name: Checksum (Windows)
if: runner.os == 'Windows'
shell: bash
env:
RELEASE_TAG: ${{ inputs.tag }}
run: sha256sum "wirerust-${RELEASE_TAG}-${{ matrix.target }}.zip" > "wirerust-${RELEASE_TAG}-${{ matrix.target }}.zip.sha256"

- name: Smoke test (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$ErrorActionPreference = 'Stop' # Catches Set-Location failure (directory missing)
Set-Location "target/${{ matrix.target }}/release"
# Use `.\wirerust.exe` (explicit current-directory prefix) — PowerShell does NOT
# search CWD for executables without it, unlike cmd.exe.
# NOTE: $ErrorActionPreference does NOT catch non-zero exit from native
# executables in PS7; the explicit LASTEXITCODE check below is load-bearing.
.\wirerust.exe --version
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: wirerust-${{ matrix.target }}
path: |
wirerust-*.tar.gz
wirerust-*.zip
wirerust-*.sha256

# ---------------------------------------------------------------------------
# Release — create or update GitHub Release with unsigned binaries
# ---------------------------------------------------------------------------
release:
name: Create Release
needs: build
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
merge-multiple: true

- name: Create or update GitHub Release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
TAG="$RELEASE_TAG"
PRERELEASE=""
if [[ "$TAG" == *-* ]]; then
PRERELEASE="--prerelease"
fi

if gh release view "$TAG" --repo "${{ github.repository }}" >/dev/null 2>&1; then
# Release already exists — upload/replace assets without touching notes or flags
DRAFT_STATUS=$(gh release view "$TAG" \
--repo "${{ github.repository }}" \
--json isDraft --jq '.isDraft')
if [ "$DRAFT_STATUS" = "true" ]; then
echo "::warning::Release $TAG is a draft. Uploading assets but NOT publishing — curator must manually publish."
fi
gh release upload "$TAG" \
--repo "${{ github.repository }}" \
--clobber \
wirerust-*.tar.gz \
wirerust-*.zip \
wirerust-*.sha256
else
# No release yet — safe to create with auto-generated notes
gh release create "$TAG" \
--repo "${{ github.repository }}" \
--title "$TAG" \
--generate-notes \
$PRERELEASE \
wirerust-*.tar.gz \
wirerust-*.zip \
wirerust-*.sha256
fi

# ---------------------------------------------------------------------------
# Sign — same as sign-and-publish.yml stable channel
# ---------------------------------------------------------------------------
sign:
name: Sign & Notarize
needs: release
if: inputs.skip_signing == false && vars.SIGNING_ENABLED == 'true'
permissions:
contents: write
environment: release
runs-on: macos-latest
outputs:
version: ${{ steps.meta.outputs.version }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: develop # need packaging scripts from develop, not the old tag
persist-credentials: false

- name: Extract version
id: meta
env:
RELEASE_TAG: ${{ inputs.tag }}
run: |
TAG="$RELEASE_TAG"
VERSION="${TAG#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Download release binaries
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
TAG="$RELEASE_TAG"
for target in x86_64-apple-darwin aarch64-apple-darwin; do
ASSET="wirerust-${TAG}-${target}.tar.gz"
echo "Downloading $ASSET..."
gh release download "$TAG" --pattern "$ASSET" --dir .
tar xzf "$ASSET"
mv wirerust "wirerust-darwin-$(echo $target | sed 's/x86_64.*/amd64/;s/aarch64.*/arm64/')"
rm "$ASSET"
done

- name: Import certificates
env:
APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_INSTALLER_CERTIFICATE_P12: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_P12 }}
APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
run: scripts/sign-and-notarize.sh import-certs

- name: Sign binaries
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: scripts/sign-and-notarize.sh sign-binaries wirerust

- name: Build packaging artifacts
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_INSTALLER_IDENTITY: ${{ secrets.APPLE_INSTALLER_IDENTITY }}
RELEASE_VERSION: ${{ steps.meta.outputs.version }}
run: scripts/sign-and-notarize.sh package wirerust "$RELEASE_VERSION"

- name: Notarize
env:
APPLE_NOTARIZATION_APPLE_ID: ${{ secrets.APPLE_NOTARIZATION_APPLE_ID }}
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
APPLE_NOTARIZATION_TEAM_ID: ${{ secrets.APPLE_NOTARIZATION_TEAM_ID }}
run: scripts/sign-and-notarize.sh notarize wirerust

- name: Verify signatures (Gatekeeper + codesign)
run: scripts/sign-and-notarize.sh verify wirerust

- name: Generate checksums
run: scripts/sign-and-notarize.sh checksums wirerust

- name: Upload signed artifacts to release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
TAG="$RELEASE_TAG"
gh release upload "$TAG" \
wirerust-darwin-arm64 \
wirerust-darwin-amd64 \
wirerust-arm64.pkg \
wirerust-amd64.pkg \
wirerust-arm64.dmg \
wirerust-amd64.dmg \
wirerust-*.sha256 \
--clobber

- name: Cleanup keychain
if: always()
run: security delete-keychain build.keychain || true

# ---------------------------------------------------------------------------
# Homebrew — update stable tap formula
# ---------------------------------------------------------------------------
homebrew:
name: Update Homebrew Tap
needs: sign
if: needs.sign.result == 'success' && inputs.update_homebrew == true && vars.HOMEBREW_TAP_REPO != ''
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit

- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: develop # need Formula/wirerust.rb template from develop
persist-credentials: false

- name: Download signed binaries from release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
TAG="$RELEASE_TAG"
gh release download "$TAG" --pattern "wirerust-darwin-arm64" --dir .
gh release download "$TAG" --pattern "wirerust-darwin-amd64" --dir .

- name: Update stable formula
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
HOMEBREW_TAP_REPO: ${{ vars.HOMEBREW_TAP_REPO }}
RELEASE_VERSION: ${{ needs.sign.outputs.version }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
scripts/update-homebrew-formula.sh \
wirerust wirerust "$RELEASE_VERSION" "$RELEASE_TAG"
Loading