Skip to content

release-app

release-app #3

Workflow file for this run

name: Release App
on:
push:
tags: ['app-v*']
workflow_dispatch:
permissions:
contents: write
jobs:
release-desktop:
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
args: '--target aarch64-apple-darwin'
rust-target: aarch64-apple-darwin
- platform: macos-latest
args: '--target x86_64-apple-darwin'
rust-target: x86_64-apple-darwin
- platform: ubuntu-22.04
args: ''
rust-target: ''
- platform: windows-latest
args: ''
rust-target: ''
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.33.0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust-target }}
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
packages/app/src-tauri/target
key: ${{ matrix.platform }}-cargo-app-${{ hashFiles('packages/app/src-tauri/Cargo.lock') }}
restore-keys: |
${{ matrix.platform }}-cargo-app-
- name: Install Linux deps
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- run: pnpm install --frozen-lockfile
- name: Extract release notes
id: notes
shell: bash
run: |
VERSION="${GITHUB_REF_NAME#app-v}"
BODY=$(awk -v v="$VERSION" '
$1 == "##" && $2 == v { capture=1; next }
capture && $1 == "##" { exit }
capture { print }
' packages/app/CHANGELOG.md)
[ -z "$BODY" ] && BODY="Release $VERSION"
{
echo "body<<RELEASE_NOTES_EOF"
echo "$BODY"
echo "RELEASE_NOTES_EOF"
} >> "$GITHUB_OUTPUT"
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: packages/app
tagName: app-v__VERSION__
releaseName: 'sbot v__VERSION__'
releaseBody: ${{ steps.notes.outputs.body }}
releaseDraft: true
prerelease: false
includeUpdaterJson: true
updaterJsonPreferNsis: true
args: ${{ matrix.args }}
publish-manifest:
needs: release-desktop
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
- name: Sync app manifest to updater channel
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
TAG: ${{ github.ref_name }}
run: |
if ! gh release download "$TAG" -R "$REPO" -p "latest.json" -O latest-app.json; then
echo "::error::latest.json not found on release $TAG — no platform produced an updater manifest"
exit 1
fi
gh release view updater -R "$REPO" >/dev/null 2>&1 || \
gh release create updater -R "$REPO" \
--title "Updater Manifests" \
--notes "Auto-maintained by CI. Hosts updater JSON for app and helper." \
--latest=false
gh release upload updater latest-app.json -R "$REPO" --clobber
gh release delete-asset "$TAG" latest.json -R "$REPO" --yes || true
release-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.33.0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- uses: android-actions/setup-android@v3
with:
packages: 'platform-tools platforms;android-34 build-tools;34.0.0 ndk;27.0.12077973'
- name: Install Rust with Android targets
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-linux-android,armv7-linux-androideabi,i686-linux-android,x86_64-linux-android
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
packages/app/src-tauri/target
key: android-cargo-app-${{ hashFiles('packages/app/src-tauri/Cargo.lock') }}
restore-keys: |
android-cargo-app-
- run: pnpm install --frozen-lockfile
- name: Decode Android keystore
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
run: |
echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/release.jks"
echo "ANDROID_KEYSTORE_PATH=$RUNNER_TEMP/release.jks" >> "$GITHUB_ENV"
- name: Build APK
working-directory: packages/app
env:
NDK_HOME: ${{ env.ANDROID_NDK_ROOT }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
run: pnpm android:build --apk
- name: Rename APK
id: rename
run: |
VERSION="${GITHUB_REF_NAME#app-v}"
[ -z "$VERSION" ] && VERSION="dev"
mkdir -p artifacts
cp packages/app/src-tauri/gen/android/app/build/outputs/apk/universal/release/*.apk \
"artifacts/sbot_${VERSION}_universal.apk"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Upload APK to release
if: startsWith(github.ref, 'refs/tags/app-v')
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: 'sbot v${{ steps.rename.outputs.version }}'
draft: true
files: artifacts/*.apk
- name: Upload APK as artifact
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: sbot-android-apk
path: artifacts/*.apk
publish-vscode:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.33.0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Build extension
run: pnpm run build:vscode
- name: Resolve version
id: version
shell: bash
run: |
PKG_VERSION=$(node -p "require('./packages/vscode-extension/package.json').version")
if [ "${{ github.event_name }}" = "push" ]; then
TAG_VERSION="${GITHUB_REF_NAME#app-v}"
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "::error::Tag version ($TAG_VERSION) does not match packages/vscode-extension/package.json version ($PKG_VERSION) — run pnpm run release:app to keep them in sync"
exit 1
fi
fi
echo "version=$PKG_VERSION" >> "$GITHUB_OUTPUT"
- name: Package VSIX
working-directory: packages/vscode-extension
run: npx --yes @vscode/vsce package --no-dependencies --out "sbot-vscode-${{ steps.version.outputs.version }}.vsix"
- name: Publish to VS Marketplace
if: github.event_name == 'push'
working-directory: packages/vscode-extension
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
shell: bash
run: |
VSIX="sbot-vscode-${{ steps.version.outputs.version }}.vsix"
set +e
OUT=$(npx --yes @vscode/vsce publish --no-dependencies --packagePath "$VSIX" 2>&1)
CODE=$?
set -e
echo "$OUT"
[ $CODE -eq 0 ] && exit 0
# Same version already on the Marketplace — skip without failing the workflow,
# so the rest of the release pipeline (desktop/android) isn't blocked by a
# re-run of the same tag. Bump the version to actually push an update.
if echo "$OUT" | grep -qi "already exists"; then
echo "::warning::v${{ steps.version.outputs.version }} already on Marketplace — skipped. Bump packages/vscode-extension/package.json to release a new version."
exit 0
fi
exit $CODE
- name: Attach VSIX to release
if: github.event_name == 'push'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
files: packages/vscode-extension/sbot-vscode-${{ steps.version.outputs.version }}.vsix
draft: true
- name: Upload VSIX as artifact
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: sbot-vscode-vsix
path: packages/vscode-extension/sbot-vscode-${{ steps.version.outputs.version }}.vsix