Repository navigation
chore(release): bump version to 1.5.7 #46
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_name: | |
| description: "Release tag to publish, e.g. v1.5.5" | |
| required: true | |
| permissions: | |
| contents: write | |
| jobs: | |
| build: | |
| strategy: | |
| # don't kill the macOS build if Windows fails (or vice versa) — release | |
| # still ships partial artifacts for users on the platform that built ok. | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: macos-latest | |
| target: aarch64-apple-darwin | |
| args: --target aarch64-apple-darwin | |
| - os: macos-latest | |
| target: x86_64-apple-darwin | |
| args: --target x86_64-apple-darwin | |
| - os: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| args: "" | |
| - os: ubuntu-22.04 | |
| target: x86_64-unknown-linux-gnu | |
| args: "" | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 45 | |
| env: | |
| # flag at job level for the cert-import step's `if:` condition. | |
| # we DON'T put the actual cert material at job level — if we did, | |
| # an empty APPLE_CERTIFICATE env var would leak into tauri-action, | |
| # which sees the var as "set" and tries to `security import` empty | |
| # data, hard-failing the bundle step. | |
| HAS_APPLE_CERT: ${{ secrets.APPLE_CERTIFICATE != '' }} | |
| # Tauri updater artifacts require a private signing key. Keep signed | |
| # auto-update releases when configured, but let unsigned/manual builds | |
| # complete without injecting empty signing env vars. | |
| HAS_TAURI_SIGNING_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY != '' }} | |
| RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag_name || github.ref_name }} | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| # Manual dispatch should build the requested tag, not the branch the | |
| # workflow UI was opened from. | |
| ref: ${{ env.RELEASE_TAG }} | |
| # need full history + tags so we can derive a per-release commit list | |
| # via `git log <prev_tag>..<this_tag>` for the changelog. | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: compute changelog since previous tag | |
| id: changelog | |
| shell: bash | |
| run: | | |
| set -e | |
| # find the most recent tag BEFORE the one we're building. `git tag --sort` | |
| # gives semver-ordered tags; we filter out the current ref and pick the next. | |
| PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${{ env.RELEASE_TAG }}$" | head -1 || true) | |
| if [ -z "$PREV_TAG" ]; then | |
| COMMITS="- first public release 🐙" | |
| DIFF_URL="" | |
| else | |
| COMMITS=$(git log "$PREV_TAG..${{ env.RELEASE_TAG }}" --pretty=format:'- %s' --no-merges --reverse) | |
| if [ -z "$COMMITS" ]; then | |
| COMMITS="- (no commit changes since $PREV_TAG — version bump only)" | |
| fi | |
| DIFF_URL="full diff: https://github.com/${{ github.repository }}/compare/$PREV_TAG...${{ env.RELEASE_TAG }}" | |
| fi | |
| echo "PREV_TAG=$PREV_TAG" >> "$GITHUB_OUTPUT" | |
| { | |
| echo "COMMITS<<COMMITS_EOF" | |
| echo "$COMMITS" | |
| echo "COMMITS_EOF" | |
| echo "DIFF_URL=$DIFF_URL" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: resolve release body | |
| id: release_body | |
| shell: bash | |
| env: | |
| COMMITS: ${{ steps.changelog.outputs.COMMITS }} | |
| DIFF_URL: ${{ steps.changelog.outputs.DIFF_URL }} | |
| TAG_NAME: ${{ env.RELEASE_TAG }} | |
| run: | | |
| set -e | |
| NOTES_FILE="docs/release-notes/${TAG_NAME}.md" | |
| { | |
| echo "BODY<<BODY_EOF" | |
| if [ -f "$NOTES_FILE" ]; then | |
| cat "$NOTES_FILE" | |
| else | |
| printf '# %s\n\n' "$TAG_NAME" | |
| printf '## What changed\n\n%s\n\n%s\n\n' "$COMMITS" "$DIFF_URL" | |
| printf '## Install\n\n' | |
| printf '**macOS Apple Silicon**: `marka.md.dmg`\n' | |
| printf '**macOS Intel**: `marka.md_intel.dmg`\n' | |
| printf '**Windows**: `marka.md_*-setup.exe`\n' | |
| printf '**Linux**: pick `.AppImage`, `.deb`, or `.rpm`\n\n' | |
| printf 'Existing users on auto-update get this on next launch.\n' | |
| fi | |
| echo "BODY_EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: setup rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| src-tauri/target | |
| key: ${{ matrix.os }}-cargo-${{ hashFiles('src-tauri/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ matrix.os }}-cargo- | |
| - name: install linux build deps | |
| if: matrix.os == 'ubuntu-22.04' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libappindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf \ | |
| libsoup-3.0-dev \ | |
| libjavascriptcoregtk-4.1-dev | |
| - name: install dependencies | |
| run: bun install | |
| - name: disable updater artifacts for unsigned build | |
| if: env.HAS_TAURI_SIGNING_KEY != 'true' | |
| shell: bash | |
| run: | | |
| node -e " | |
| const fs = require('fs'); | |
| const path = 'src-tauri/tauri.conf.json'; | |
| const cfg = JSON.parse(fs.readFileSync(path, 'utf8')); | |
| cfg.bundle.createUpdaterArtifacts = false; | |
| fs.writeFileSync(path, JSON.stringify(cfg, null, 2)); | |
| " | |
| - name: import apple cert + propagate signing env (macOS only) | |
| if: matrix.os == 'macos-latest' && env.HAS_APPLE_CERT == 'true' | |
| env: | |
| APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | |
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} | |
| APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| run: | | |
| echo "$APPLE_CERTIFICATE" | base64 --decode > /tmp/cert.p12 | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain | |
| security default-keychain -s build.keychain | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain | |
| security set-keychain-settings -t 3600 -u build.keychain | |
| security import /tmp/cert.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain | |
| rm /tmp/cert.p12 | |
| # propagate the signing env to later steps so tauri-action can read it. | |
| # this step is skipped when HAS_APPLE_CERT=false or non-macOS → these | |
| # vars are never written → tauri-action's env contains no APPLE_* → | |
| # Tauri auto-skips signing instead of running `codesign --sign ""`. | |
| { | |
| echo "APPLE_SIGNING_IDENTITY=$APPLE_SIGNING_IDENTITY" | |
| echo "APPLE_ID=$APPLE_ID" | |
| echo "APPLE_PASSWORD=$APPLE_PASSWORD" | |
| echo "APPLE_TEAM_ID=$APPLE_TEAM_ID" | |
| } >> "$GITHUB_ENV" | |
| - name: build + release (signed updater) | |
| if: env.HAS_TAURI_SIGNING_KEY == 'true' | |
| uses: tauri-apps/tauri-action@v0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Apple signing env injected by the cert-import step via $GITHUB_ENV | |
| # (macOS only — Windows runner never sees these). | |
| # Tauri updater signing — signs the bundle + emits latest.json. Set on | |
| # both runners so macOS .app.tar.gz.sig and Windows .nsis.zip.sig are | |
| # produced and the updater can verify upgrades cross-platform. | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| with: | |
| tagName: ${{ env.RELEASE_TAG }} | |
| releaseName: "marka.md ${{ env.RELEASE_TAG }}" | |
| releaseBody: ${{ steps.release_body.outputs.BODY }} | |
| # publish as a DRAFT so the matrix runners can both upload artifacts | |
| # (including their per-platform latest.json entries) without racing | |
| # to overwrite each other on the same live release. the publish-release | |
| # job below flips the draft to public AFTER both legs complete + a | |
| # consolidated latest.json with both `darwin-aarch64` and | |
| # `windows-x86_64` platforms is in place. | |
| # ref: https://v2.tauri.app/distribute/pipelines/github/ | |
| releaseDraft: true | |
| prerelease: false | |
| args: ${{ matrix.args }} | |
| - name: build + release (unsigned, no updater artifacts) | |
| if: env.HAS_TAURI_SIGNING_KEY != 'true' | |
| uses: tauri-apps/tauri-action@v0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tagName: ${{ env.RELEASE_TAG }} | |
| releaseName: "marka.md ${{ env.RELEASE_TAG }}" | |
| releaseBody: ${{ steps.release_body.outputs.BODY }} | |
| releaseDraft: true | |
| prerelease: false | |
| args: ${{ matrix.args }} | |
| # tauri-action emits `marka.md_<version>_<arch>.dmg` by default. Rename | |
| # per arch so users get clean filenames + the landing dropdown can keep | |
| # linking to `marka.md.dmg` (apple-silicon default). Intel gets a clear | |
| # `_intel` suffix. Both rename steps are guarded by their matrix target | |
| # so the two macOS legs don't race. | |
| - name: rename dmg → marka.md.dmg (apple silicon) | |
| if: matrix.target == 'aarch64-apple-darwin' && success() | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -e | |
| RELEASE_ID=$(gh api repos/${{ github.repository }}/releases --jq '.[] | select(.tag_name == "${{ env.RELEASE_TAG }}") | .id' | head -1) | |
| if [ -z "$RELEASE_ID" ]; then | |
| echo "no release found for tag ${{ env.RELEASE_TAG }} — skipping rename" | |
| exit 0 | |
| fi | |
| ASSET_ID=$(gh api "repos/${{ github.repository }}/releases/$RELEASE_ID/assets" --jq '.[] | select(.name | test("aarch64.*\\.dmg$")) | .id' | head -1) | |
| if [ -n "$ASSET_ID" ]; then | |
| echo "renaming aarch64 dmg asset $ASSET_ID → marka.md.dmg" | |
| gh api "repos/${{ github.repository }}/releases/assets/$ASSET_ID" -X PATCH -f name='marka.md.dmg' | |
| else | |
| echo "no aarch64 dmg asset found — skipping rename" | |
| fi | |
| - name: rename dmg → marka.md_intel.dmg (intel) | |
| if: matrix.target == 'x86_64-apple-darwin' && success() | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -e | |
| RELEASE_ID=$(gh api repos/${{ github.repository }}/releases --jq '.[] | select(.tag_name == "${{ env.RELEASE_TAG }}") | .id' | head -1) | |
| if [ -z "$RELEASE_ID" ]; then | |
| echo "no release found for tag ${{ env.RELEASE_TAG }} — skipping rename" | |
| exit 0 | |
| fi | |
| ASSET_ID=$(gh api "repos/${{ github.repository }}/releases/$RELEASE_ID/assets" --jq '.[] | select(.name | test("x64.*\\.dmg$")) | .id' | head -1) | |
| if [ -n "$ASSET_ID" ]; then | |
| echo "renaming intel dmg asset $ASSET_ID → marka.md_intel.dmg" | |
| gh api "repos/${{ github.repository }}/releases/assets/$ASSET_ID" -X PATCH -f name='marka.md_intel.dmg' | |
| else | |
| echo "no dmg asset found — skipping rename" | |
| fi | |
| # flip the draft release to public AFTER both matrix runners have finished | |
| # uploading their artifacts + latest.json entries. this prevents the | |
| # cross-platform race where each runner could overwrite the other's | |
| # latest.json on a live release. | |
| publish-release: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| env: | |
| RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag_name || github.ref_name }} | |
| steps: | |
| - name: publish draft release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "publishing draft release for ${{ env.RELEASE_TAG }}" | |
| gh release edit "${{ env.RELEASE_TAG }}" \ | |
| --repo "${{ github.repository }}" \ | |
| --draft=false \ | |
| --latest | |
| # fires a Vercel deploy hook after a release publishes so markamd.vercel.app | |
| # rebuilds and picks up the new version automatically (no manual empty | |
| # commit needed). gracefully no-ops if the secret isn't set yet. | |
| # NOTE: GitHub Actions does not allow `secrets.*` in `if:` expressions — | |
| # they must be evaluated through env first (same pattern as HAS_APPLE_CERT). | |
| notify-site: | |
| needs: publish-release | |
| runs-on: ubuntu-latest | |
| env: | |
| HAS_HOOK: ${{ secrets.VERCEL_DEPLOY_HOOK != '' }} | |
| steps: | |
| - name: ping vercel deploy hook | |
| if: env.HAS_HOOK == 'true' | |
| env: | |
| DEPLOY_HOOK: ${{ secrets.VERCEL_DEPLOY_HOOK }} | |
| run: | | |
| echo "triggering markamd-site rebuild for ${{ github.event_name == 'workflow_dispatch' && inputs.tag_name || github.ref_name }}" | |
| curl -fsS -X POST "$DEPLOY_HOOK" | |
| - name: no hook configured | |
| if: env.HAS_HOOK != 'true' | |
| run: echo "VERCEL_DEPLOY_HOOK secret not set — skipping site rebuild" |