From 6463cdff589439bf2294d729bb4aba9ae932ec53 Mon Sep 17 00:00:00 2001 From: webadderall <131426131+webadderall@users.noreply.github.com> Date: Sat, 28 Mar 2026 20:42:04 +1100 Subject: [PATCH] feat: add updater release infrastructure --- .github/workflows/build.yml | 64 ++-- .github/workflows/homebrew-tap.yml | 34 +- .github/workflows/release.yml | 525 ++++++++++++++++++----------- README.md | 2 + RELEASING.md | 90 +++++ electron-builder.json5 | 25 +- electron/electron-env.d.ts | 12 + electron/main.ts | 84 ++++- electron/preload.ts | 24 ++ electron/updater.ts | 220 ++++++++++-- electron/windows.ts | 4 + src/App.tsx | 82 +++++ 12 files changed, 904 insertions(+), 262 deletions(-) create mode 100644 RELEASING.md diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1574c835..5285c9b7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,24 +9,27 @@ jobs: runs-on: windows-latest steps: - name: Checkout code - uses: actions/checkout@v3 - + uses: actions/checkout@v4 + - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '22' - + - name: Install dependencies - run: npm ci - + run: npm ci --ignore-scripts + - name: Install app dependencies run: npx electron-builder install-app-deps - + - name: Build Windows app - run: npm run build:win - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + shell: pwsh + run: | + npm run build:platform-native-helpers + npx tsc + npx vite build + npx electron-builder --win nsis --x64 --publish never + - name: Upload Windows build uses: actions/upload-artifact@v4 with: @@ -38,63 +41,72 @@ jobs: runs-on: macos-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '22' - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies - run: npm ci + run: npm ci --ignore-scripts - name: Install app dependencies run: npx electron-builder install-app-deps - name: Build macOS app - run: npm run build:mac - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + npm run build:native-helpers + npx tsc + npx vite build + npx electron-builder --mac dmg zip --publish never - name: Upload macOS build uses: actions/upload-artifact@v4 with: name: macos-installer - path: release/**/*.dmg + path: | + release/**/*.dmg + release/**/*.zip + release/latest-mac.yml retention-days: 30 build-linux: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '22' - name: Install dependencies - run: npm ci + run: npm ci --ignore-scripts - name: Install app dependencies run: npx electron-builder install-app-deps - name: Build Linux app - run: npm run build:linux - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + npm run build:platform-native-helpers + npx tsc + npx vite build + npx electron-builder --linux AppImage --x64 --publish never - name: Upload Linux build uses: actions/upload-artifact@v4 with: name: linux-installer - path: release/**/*.AppImage + path: | + release/**/*.AppImage + release/latest-linux.yml retention-days: 30 diff --git a/.github/workflows/homebrew-tap.yml b/.github/workflows/homebrew-tap.yml index 08df4aea..5f8549ec 100644 --- a/.github/workflows/homebrew-tap.yml +++ b/.github/workflows/homebrew-tap.yml @@ -1,8 +1,6 @@ name: Update Homebrew Tap on: - release: - types: [published] workflow_dispatch: inputs: tag: @@ -37,11 +35,7 @@ jobs: id: tag shell: bash run: | - if [ "${{ github.event_name }}" = "release" ]; then - TAG="${{ github.event.release.tag_name }}" - else - TAG="${{ github.event.inputs.tag }}" - fi + TAG="${{ github.event.inputs.tag }}" if [ -z "$TAG" ]; then echo "Release tag is empty" @@ -55,21 +49,33 @@ jobs: - name: Download release artifacts shell: bash run: | + set -euo pipefail mkdir -p /tmp/recordly-release gh release download "${{ steps.tag.outputs.tag }}" \ --repo "${{ github.repository }}" \ --dir /tmp/recordly-release \ - --pattern "Recordly-arm64.dmg" \ - --pattern "Recordly-x64.dmg" + --pattern "Recordly-*-arm64.dmg" \ + --pattern "Recordly-*-x64.dmg" - name: Compute checksums id: sha shell: bash run: | - SHA_ARM=$(sha256sum /tmp/recordly-release/Recordly-arm64.dmg | awk '{print $1}') - SHA_INTEL=$(sha256sum /tmp/recordly-release/Recordly-x64.dmg | awk '{print $1}') + set -euo pipefail + ARM_FILE=$(find /tmp/recordly-release -maxdepth 1 -name 'Recordly-*-arm64.dmg' | head -n 1) + INTEL_FILE=$(find /tmp/recordly-release -maxdepth 1 -name 'Recordly-*-x64.dmg' | head -n 1) + + if [ -z "$ARM_FILE" ] || [ -z "$INTEL_FILE" ]; then + echo "Unable to locate macOS release artifacts for ${{ steps.tag.outputs.tag }}" + exit 1 + fi + + SHA_ARM=$(sha256sum "$ARM_FILE" | awk '{print $1}') + SHA_INTEL=$(sha256sum "$INTEL_FILE" | awk '{print $1}') echo "arm=$SHA_ARM" >> "$GITHUB_OUTPUT" echo "intel=$SHA_INTEL" >> "$GITHUB_OUTPUT" + echo "arm_file=$(basename "$ARM_FILE")" >> "$GITHUB_OUTPUT" + echo "intel_file=$(basename "$INTEL_FILE")" >> "$GITHUB_OUTPUT" - name: Clone tap repository shell: bash @@ -94,12 +100,12 @@ jobs: on_arm do sha256 "__SHA_ARM__" - url "https://github.com/__REPO__/releases/download/__TAG__/Recordly-arm64.dmg" + url "https://github.com/__REPO__/releases/download/__TAG__/__ARM_FILE__" end on_intel do sha256 "__SHA_INTEL__" - url "https://github.com/__REPO__/releases/download/__TAG__/Recordly-x64.dmg" + url "https://github.com/__REPO__/releases/download/__TAG__/__INTEL_FILE__" end name "Recordly" @@ -115,6 +121,8 @@ jobs: sed -i "s/__SHA_INTEL__/${{ steps.sha.outputs.intel }}/g" Casks/recordly.rb sed -i "s#__REPO__#${{ github.repository }}#g" Casks/recordly.rb sed -i "s#__TAG__#${{ steps.tag.outputs.tag }}#g" Casks/recordly.rb + sed -i "s#__ARM_FILE__#${{ steps.sha.outputs.arm_file }}#g" Casks/recordly.rb + sed -i "s#__INTEL_FILE__#${{ steps.sha.outputs.intel_file }}#g" Casks/recordly.rb if git diff --quiet; then echo "changed=false" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ec802e49..8f154120 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,93 +1,91 @@ -name: Release Builds +name: Publish Release on: + release: + types: [published, prereleased] workflow_dispatch: inputs: - source_ref: - description: Branch, tag, or commit to build from - required: true - default: main - type: string tag_name: - description: Release tag to create or update + description: Existing release tag to rebuild and publish required: true type: string - release_name: - description: Release title - required: true - type: string - release_notes: - description: Optional release notes - required: false - type: string - make_latest: - description: Mark this release as the latest release - required: true - default: true - type: boolean permissions: contents: write + actions: write + +concurrency: + group: release-${{ github.event.release.tag_name || github.event.inputs.tag_name || github.run_id }} + cancel-in-progress: false jobs: - validate-release: - name: Prepare release input + prepare-release: + name: Prepare release runs-on: ubuntu-latest outputs: + tag_name: ${{ steps.prepare.outputs.tag_name }} package_version: ${{ steps.prepare.outputs.package_version }} source_sha: ${{ steps.prepare.outputs.source_sha }} + prerelease: ${{ steps.prepare.outputs.prerelease }} steps: - - name: Checkout source ref + - name: Checkout release source uses: actions/checkout@v4 with: - ref: ${{ github.event.inputs.source_ref }} + ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.event.inputs.tag_name }} fetch-depth: 0 - - name: Sync version with release tag + - name: Validate release tag id: prepare shell: bash run: | set -euo pipefail - INPUT_REF="${{ github.event.inputs.source_ref }}" - TAG_VERSION="${{ github.event.inputs.tag_name }}" - TAG_VERSION="${TAG_VERSION#v}" - SOURCE_BRANCH="" - - if git ls-remote --exit-code --heads origin "$INPUT_REF" >/dev/null 2>&1; then - SOURCE_BRANCH="$INPUT_REF" + if [ "${{ github.event_name }}" = "release" ]; then + TAG_NAME="${{ github.event.release.tag_name }}" + IS_PRERELEASE="${{ github.event.release.prerelease }}" + else + TAG_NAME="${{ github.event.inputs.tag_name }}" + IS_PRERELEASE="false" fi + if [ -z "$TAG_NAME" ]; then + echo "Release tag is required." + exit 1 + fi + + TAG_VERSION="${TAG_NAME#v}" PACKAGE_VERSION=$(node -p "require('./package.json').version") if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then - if [ -z "$SOURCE_BRANCH" ]; then - echo "Release tag version ($TAG_VERSION) does not match package.json version ($PACKAGE_VERSION), and source_ref '$INPUT_REF' is not a branch that can be updated automatically." - exit 1 - fi - - npm version "$TAG_VERSION" --no-git-tag-version - - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add package.json package-lock.json - git commit -m "chore(release): bump version to v$TAG_VERSION" - git push origin "HEAD:$SOURCE_BRANCH" - - PACKAGE_VERSION=$(node -p "require('./package.json').version") + echo "Release tag version ($TAG_VERSION) does not match package.json version ($PACKAGE_VERSION)." + exit 1 fi + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + gh release view "$TAG_NAME" --repo "${{ github.repository }}" >/dev/null 2>&1 || \ + gh release create "$TAG_NAME" --repo "${{ github.repository }}" --verify-tag --draft --title "$TAG_NAME" + fi + + echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT" echo "package_version=$PACKAGE_VERSION" >> "$GITHUB_OUTPUT" echo "source_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + echo "prerelease=$IS_PRERELEASE" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} build-macos-x64: name: Build macOS x64 - needs: validate-release + needs: prepare-release runs-on: macos-15-intel + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} steps: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ needs.validate-release.outputs.source_sha }} + ref: ${{ needs.prepare-release.outputs.source_sha }} - name: Setup Node.js uses: actions/setup-node@v4 @@ -100,8 +98,36 @@ jobs: with: python-version: '3.11' + - name: Validate macOS signing secrets + shell: bash + env: + APPLE_SIGNING_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_SIGNING_CERTIFICATE_P12_BASE64 }} + APPLE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_SIGNING_CERTIFICATE_PASSWORD }} + run: | + set -euo pipefail + for name in APPLE_SIGNING_CERTIFICATE_P12_BASE64 APPLE_SIGNING_CERTIFICATE_PASSWORD APPLE_ID APPLE_APP_SPECIFIC_PASSWORD APPLE_TEAM_ID; do + if [ -z "${!name:-}" ]; then + echo "Missing required macOS release secret: $name" + exit 1 + fi + done + + - name: Prepare macOS signing certificate + shell: bash + env: + APPLE_SIGNING_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_SIGNING_CERTIFICATE_P12_BASE64 }} + APPLE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_SIGNING_CERTIFICATE_PASSWORD }} + run: | + set -euo pipefail + CERT_PATH="$RUNNER_TEMP/apple-signing-cert.p12" + echo "$APPLE_SIGNING_CERTIFICATE_P12_BASE64" | base64 --decode > "$CERT_PATH" + { + echo "CSC_LINK=$CERT_PATH" + echo "CSC_KEY_PASSWORD=$APPLE_SIGNING_CERTIFICATE_PASSWORD" + } >> "$GITHUB_ENV" + - name: Install dependencies - run: npm ci + run: npm ci --ignore-scripts - name: Install app dependencies run: npx electron-builder install-app-deps @@ -113,25 +139,255 @@ jobs: run: | npx tsc npx vite build - npx electron-builder --mac dmg --x64 --publish never - mv release/Recordly.dmg release/Recordly-x64.dmg + npx electron-builder --mac dmg zip --x64 --publish always - - name: Upload macOS x64 artifact + - name: Upload macOS x64 artifacts uses: actions/upload-artifact@v4 with: - name: macos-x64 - path: release/Recordly-x64.dmg + name: macos-x64-release + path: | + release/*.dmg + release/*.zip + release/latest-mac.yml if-no-files-found: error build-macos-arm64: name: Build macOS arm64 - needs: validate-release + needs: prepare-release runs-on: macos-14 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} steps: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ needs.validate-release.outputs.source_sha }} + ref: ${{ needs.prepare-release.outputs.source_sha }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Validate macOS signing secrets + shell: bash + env: + APPLE_SIGNING_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_SIGNING_CERTIFICATE_P12_BASE64 }} + APPLE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_SIGNING_CERTIFICATE_PASSWORD }} + run: | + set -euo pipefail + for name in APPLE_SIGNING_CERTIFICATE_P12_BASE64 APPLE_SIGNING_CERTIFICATE_PASSWORD APPLE_ID APPLE_APP_SPECIFIC_PASSWORD APPLE_TEAM_ID; do + if [ -z "${!name:-}" ]; then + echo "Missing required macOS release secret: $name" + exit 1 + fi + done + + - name: Prepare macOS signing certificate + shell: bash + env: + APPLE_SIGNING_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_SIGNING_CERTIFICATE_P12_BASE64 }} + APPLE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_SIGNING_CERTIFICATE_PASSWORD }} + run: | + set -euo pipefail + CERT_PATH="$RUNNER_TEMP/apple-signing-cert.p12" + echo "$APPLE_SIGNING_CERTIFICATE_P12_BASE64" | base64 --decode > "$CERT_PATH" + { + echo "CSC_LINK=$CERT_PATH" + echo "CSC_KEY_PASSWORD=$APPLE_SIGNING_CERTIFICATE_PASSWORD" + } >> "$GITHUB_ENV" + + - name: Install dependencies + run: npm ci --ignore-scripts + + - name: Install app dependencies + run: npx electron-builder install-app-deps + + - name: Build native macOS helpers + run: npm run build:native-helpers + + - name: Build macOS arm64 + run: | + npx tsc + npx vite build + npx electron-builder --mac dmg zip --arm64 --publish always + + - name: Upload macOS arm64 artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-arm64-release + path: | + release/*.dmg + release/*.zip + release/latest-mac.yml + if-no-files-found: error + + merge-macos-update-metadata: + name: Merge macOS update metadata + needs: + - prepare-release + - build-macos-x64 + - build-macos-arm64 + runs-on: ubuntu-latest + steps: + - name: Download macOS x64 artifacts + uses: actions/download-artifact@v4 + with: + name: macos-x64-release + path: release-assets/macos-x64 + + - name: Download macOS arm64 artifacts + uses: actions/download-artifact@v4 + with: + name: macos-arm64-release + path: release-assets/macos-arm64 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install PyYAML + run: python -m pip install pyyaml + + - name: Merge latest-mac.yml + shell: bash + run: | + set -euo pipefail + mkdir -p release-assets/merged + python <<'PY' + from pathlib import Path + import yaml + + x64_info = yaml.safe_load(Path('release-assets/macos-x64/latest-mac.yml').read_text()) + arm64_info = yaml.safe_load(Path('release-assets/macos-arm64/latest-mac.yml').read_text()) + + merged_files = [] + seen_urls = set() + for info in (x64_info, arm64_info): + for file_info in info.get('files', []): + url = file_info.get('url') + if url and url not in seen_urls: + seen_urls.add(url) + merged_files.append(file_info) + + if not merged_files: + raise SystemExit('No macOS update files found to merge.') + + preferred = next((item for item in merged_files if 'x64' in item.get('url', '')), merged_files[0]) + merged = dict(x64_info) + merged['files'] = merged_files + merged['path'] = preferred.get('url', merged.get('path')) + merged['sha512'] = preferred.get('sha512', merged.get('sha512')) + if not merged.get('releaseDate') and arm64_info.get('releaseDate'): + merged['releaseDate'] = arm64_info['releaseDate'] + + Path('release-assets/merged/latest-mac.yml').write_text( + yaml.safe_dump(merged, sort_keys=False) + ) + PY + + - name: Upload merged latest-mac.yml to release + shell: bash + run: | + gh release upload "${{ needs.prepare-release.outputs.tag_name }}" \ + release-assets/merged/latest-mac.yml \ + --repo "${{ github.repository }}" \ + --clobber + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build-windows-x64: + name: Build Windows x64 + needs: prepare-release + runs-on: windows-latest + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare-release.outputs.source_sha }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Validate Windows signing secrets + shell: pwsh + env: + WINDOWS_SIGNING_CERTIFICATE_P12_BASE64: ${{ secrets.WINDOWS_SIGNING_CERTIFICATE_P12_BASE64 }} + WINDOWS_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_SIGNING_CERTIFICATE_PASSWORD }} + run: | + foreach ($name in @('WINDOWS_SIGNING_CERTIFICATE_P12_BASE64', 'WINDOWS_SIGNING_CERTIFICATE_PASSWORD')) { + $value = [Environment]::GetEnvironmentVariable($name) + if ([string]::IsNullOrWhiteSpace($value)) { + Write-Error "Missing required Windows release secret: $name" + exit 1 + } + } + + - name: Prepare Windows signing certificate + shell: pwsh + env: + WINDOWS_SIGNING_CERTIFICATE_P12_BASE64: ${{ secrets.WINDOWS_SIGNING_CERTIFICATE_P12_BASE64 }} + WINDOWS_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_SIGNING_CERTIFICATE_PASSWORD }} + run: | + $certPath = Join-Path $env:RUNNER_TEMP 'windows-signing-cert.p12' + [IO.File]::WriteAllBytes($certPath, [Convert]::FromBase64String($env:WINDOWS_SIGNING_CERTIFICATE_P12_BASE64)) + Add-Content -Path $env:GITHUB_ENV -Value "WIN_CSC_LINK=$certPath" + Add-Content -Path $env:GITHUB_ENV -Value "WIN_CSC_KEY_PASSWORD=$env:WINDOWS_SIGNING_CERTIFICATE_PASSWORD" + + - name: Install dependencies + run: npm ci --ignore-scripts + + - name: Install app dependencies + run: npx electron-builder install-app-deps + + - name: Build Windows x64 + shell: pwsh + run: | + npm run build:platform-native-helpers + npx tsc + npx vite build + npx electron-builder --win nsis --x64 --publish always + + - name: Upload Windows x64 artifacts + uses: actions/upload-artifact@v4 + with: + name: windows-x64-release + path: | + release/*.exe + release/*.blockmap + release/latest*.yml + if-no-files-found: error + + build-linux-x64: + name: Build Linux x64 + needs: prepare-release + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare-release.outputs.source_sha }} - name: Setup Node.js uses: actions/setup-node@v4 @@ -150,154 +406,41 @@ jobs: - name: Install app dependencies run: npx electron-builder install-app-deps - - name: Build native macOS helpers - run: npm run build:native-helpers - - - name: Build macOS arm64 - run: | - npx tsc - npx vite build - npx electron-builder --mac dmg --arm64 --publish never - mv release/Recordly.dmg release/Recordly-arm64.dmg - - - name: Upload macOS arm64 artifact - uses: actions/upload-artifact@v4 - with: - name: macos-arm64 - path: release/Recordly-arm64.dmg - if-no-files-found: error - - build-windows-x64: - name: Build Windows x64 - needs: validate-release - runs-on: windows-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ needs.validate-release.outputs.source_sha }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: npm - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install dependencies - run: npm ci - - - name: Install app dependencies - run: npx electron-builder install-app-deps - - - name: Build Windows x64 - shell: pwsh - run: | - npm run build:cursor-monitor - npx tsc - npx vite build - npx electron-builder --win nsis --x64 --publish never - Rename-Item -Path release/Recordly.exe -NewName Recordly-windows-x64.exe - - - name: Upload Windows x64 artifact - uses: actions/upload-artifact@v4 - with: - name: windows-x64 - path: release/Recordly-windows-x64.exe - if-no-files-found: error - - build-linux-x64: - name: Build Linux x64 - needs: validate-release - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ needs.validate-release.outputs.source_sha }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: npm - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install dependencies - run: npm ci - - - name: Install app dependencies - run: npx electron-builder install-app-deps - - name: Build Linux x64 run: | + export CSC_IDENTITY_AUTO_DISCOVERY=false + npm run build:platform-native-helpers npx tsc npx vite build - npx electron-builder --linux AppImage --x64 --publish never - mv release/Recordly.AppImage release/Recordly-linux-x64.AppImage + npx electron-builder --linux AppImage --x64 --publish always - - name: Upload Linux x64 artifact + - name: Upload Linux x64 artifacts uses: actions/upload-artifact@v4 with: - name: linux-x64 - path: release/Recordly-linux-x64.AppImage + name: linux-x64-release + path: | + release/*.AppImage + release/*.blockmap + release/latest-linux.yml if-no-files-found: error - publish-release: - name: Publish release + trigger-homebrew-update: + name: Trigger Homebrew tap update needs: - - validate-release + - prepare-release - build-macos-x64 - build-macos-arm64 + - merge-macos-update-metadata - build-windows-x64 - build-linux-x64 runs-on: ubuntu-latest + if: needs.prepare-release.outputs.prerelease != 'true' steps: - - name: Download macOS x64 artifact - uses: actions/download-artifact@v4 - with: - name: macos-x64 - path: release-assets - - - name: Download macOS arm64 artifact - uses: actions/download-artifact@v4 - with: - name: macos-arm64 - path: release-assets - - - name: Download Windows x64 artifact - uses: actions/download-artifact@v4 - with: - name: windows-x64 - path: release-assets - - - name: Download Linux x64 artifact - uses: actions/download-artifact@v4 - with: - name: linux-x64 - path: release-assets - - - name: Create or update release - uses: ncipollo/release-action@v1 - with: - tag: ${{ github.event.inputs.tag_name }} - commit: ${{ needs.validate-release.outputs.source_sha }} - name: ${{ github.event.inputs.release_name }} - body: ${{ github.event.inputs.release_notes }} - makeLatest: ${{ github.event.inputs.make_latest }} - allowUpdates: true - replacesArtifacts: true - artifactErrorsFailBuild: true - artifacts: | - release-assets/Recordly-arm64.dmg - release-assets/Recordly-x64.dmg - release-assets/Recordly-windows-x64.exe - release-assets/Recordly-linux-x64.AppImage + - name: Dispatch Homebrew tap workflow + shell: bash + run: | + gh workflow run homebrew-tap.yml \ + --repo "${{ github.repository }}" \ + -f tag="${{ needs.prepare-release.outputs.tag_name }}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index c5b8380b..bc0d1015 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ Language: EN | [简中](README.zh-CN.md) ### Create polished, pro-grade screen recordings. [Recordly](https://www.recordly.dev) is an open-source screen recorder and editor for walkthroughs, demos, tutorials, product videos, and social clips. Record a screen or window, jump straight into the editor, and export a polished result with cursor effects, zooms, backgrounds, annotations, webcam overlays, and more. +Release automation, signing, notarization, and cross-platform auto-update publishing are documented in [RELEASING.md](RELEASING.md). +
+ {payload.isPreview ? "Update Toast Preview" : `Recordly ${payload.version} is ready`} +
+ {payload.isPreview ? ( + + Dev + + ) : null} +{payload.detail}
+