Skip to content

Release (stable)

Release (stable) #4

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
version:
description: "Release version (e.g. 0.2.0, 1.0.0)"
required: true
type: string
dry_run:
description: "Dry run — skip tag push and build (for testing)"
required: false
type: boolean
default: false
permissions:
contents: write
jobs:
# ── Step 1: Bump version, commit, tag, push ──────────────────────
prepare:
runs-on: ubuntu-latest
outputs:
tag: v${{ inputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "24"
- name: Setup pnpm
uses: pnpm/action-setup@v6
- name: Validate version format
run: |
if ! echo "${{ inputs.version }}" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
echo "::error::Invalid version format. Use semver like 0.2.0 or 1.0.0-beta.1"
exit 1
fi
if git rev-parse "v${{ inputs.version }}" >/dev/null 2>&1; then
echo "::error::Tag v${{ inputs.version }} already exists"
exit 1
fi
- name: Bump version in package.json
run: |
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
pkg.version = '${{ inputs.version }}';
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
"
- name: Commit and tag
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add package.json
if git diff --cached --quiet; then
echo "package.json already at v${{ inputs.version }}; skipping bump commit."
else
git commit -m "release: v${{ inputs.version }}"
fi
git tag "v${{ inputs.version }}"
- name: Push commit and tag
if: ${{ !inputs.dry_run }}
run: |
git push origin HEAD
git push origin "v${{ inputs.version }}"
# ── Step 2: Build installers for each platform ───────────────────
build:
needs: prepare
if: ${{ !inputs.dry_run }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
artifact: dist-windows
- os: ubuntu-latest
artifact: dist-linux
- os: macos-latest
artifact: dist-mac
runs-on: ${{ matrix.os }}
steps:
- name: Checkout tag
uses: actions/checkout@v6
with:
ref: ${{ needs.prepare.outputs.tag }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "24"
- name: Setup pnpm
uses: pnpm/action-setup@v6
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build app
run: pnpm run build
shell: bash
env:
SENTRY_DSN: ${{ vars.SENTRY_DSN }}
SENTRY_ENVIRONMENT: ${{ vars.SENTRY_ENVIRONMENT || 'production' }}
POSTHOG_ENABLED: ${{ vars.POSTHOG_ENABLED || '1' }}
POSTHOG_KEY: ${{ vars.POSTHOG_KEY }}
POSTHOG_HOST: ${{ vars.POSTHOG_HOST || 'https://us.i.posthog.com' }}
POSTHOG_ENABLE_DEV: "0"
- name: Upload Sentry source maps
if: matrix.os == 'ubuntu-latest'
run: |
# Local `pnpm run dist` cleans source maps before packaging. Release CI
# uploads them from the build output first, then removes them below.
if [ -z "$SENTRY_AUTH_TOKEN" ] || [ -z "$SENTRY_ORG" ] || [ -z "$SENTRY_PROJECT" ]; then
echo "Sentry secrets are not configured; skipping source map upload."
exit 0
fi
pnpm run sentry:sourcemaps
shell: bash
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ vars.SENTRY_ORG }}
SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }}
- name: Remove packaged source maps
run: pnpm run clean:sourcemaps
shell: bash
- name: Package
run: |
if [ "${{ matrix.os }}" = "windows-latest" ]; then
pnpm run prepare:package-assets
pnpm exec electron-builder --win
else
if [ "${{ matrix.os }}" = "macos-latest" ]; then
pnpm run prepare:agent-plugins
pnpm exec electron-builder --mac
else
pnpm run prepare:package-assets
pnpm exec electron-builder --linux
fi
fi
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload built artifacts
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.artifact }}
path: |
release/Lightcode-*.exe
release/Lightcode-*.dmg
release/Lightcode-*.AppImage
release/Lightcode-*.deb
release/latest*.yml
release/*.blockmap
if-no-files-found: error
retention-days: 7
# ── Step 3: Create GitHub Release with auto-generated notes ──────
release:
needs: [prepare, build]
if: ${{ !inputs.dry_run }}
runs-on: ubuntu-latest
steps:
- name: Download all build artifacts
uses: actions/download-artifact@v8
with:
path: release-assets
pattern: dist-*
merge-multiple: true
- name: List release assets
run: ls -lh release-assets
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.prepare.outputs.tag }}
name: Lightcode ${{ needs.prepare.outputs.tag }}
generate_release_notes: true
fail_on_unmatched_files: true
files: release-assets/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ── Step 4: Bump master to next dev version ────────────────────────
post-release:
needs: [prepare, release]
if: ${{ !inputs.dry_run }}
runs-on: ubuntu-latest
steps:
- name: Checkout master
uses: actions/checkout@v6
with:
ref: master
fetch-depth: 1
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "24"
- name: Setup pnpm
uses: pnpm/action-setup@v6
- name: Bump to next patch-dev version
run: |
node -e "
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const v = p.version.split('.').map(Number);
p.version = v[0] + '.' + v[1] + '.' + (v[2] + 1) + '-dev';
fs.writeFileSync('package.json', JSON.stringify(p, null, 2) + '\n');
"
- name: Commit and push
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add package.json
git commit -m "chore: bump to next dev version"
git push