Initial public release

This commit is contained in:
Bohdan Triapitsyn
2025-12-07 19:32:53 +02:00
commit 4b2edf7318
319 changed files with 81600 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
name: opencode
on:
issue_comment:
types: [created]
jobs:
opencode:
if: |
contains(github.event.comment.body, ' /oc') ||
startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run opencode
uses: sst/opencode/github@latest
env:
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}
with:
model: zai-coding-plan/glm-4.6
+269
View File
@@ -0,0 +1,269 @@
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 0.1.0)'
required: true
type: string
dry_run:
description: 'Dry run (skip publishing)'
required: false
default: false
type: boolean
env:
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: short
permissions:
contents: write
jobs:
create-release:
runs-on: ubuntu-latest
outputs:
release_id: ${{ steps.create_release.outputs.id }}
release_upload_url: ${{ steps.create_release.outputs.upload_url }}
version: ${{ steps.get_version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Get version
id: get_version
run: |
if [[ -n "${{ github.event.inputs.version }}" ]]; then
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
else
echo "version=0.0.0-dev" >> $GITHUB_OUTPUT
fi
- name: Extract changelog for release
env:
VERSION: ${{ steps.get_version.outputs.version }}
run: |
node - <<'NODE'
const fs = require('fs');
const version = process.env.VERSION;
const changelogPath = 'CHANGELOG.md';
if (!fs.existsSync(changelogPath)) {
throw new Error('CHANGELOG.md not found; add it before releasing.');
}
const changelog = fs.readFileSync(changelogPath, 'utf8');
const sections = changelog.split(/^## /m);
const section = sections.find(s => s.startsWith('[' + version + ']'));
if (!section) {
throw new Error('Changelog section [' + version + '] not found. Add a section like "## [' + version + '] - YYYY-MM-DD".');
}
const content = ('## ' + section).trim();
fs.mkdirSync('artifacts', { recursive: true });
fs.writeFileSync('artifacts/release-notes.md', content + '\n');
NODE
- name: Create GitHub Release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.get_version.outputs.version }}
draft: true
generate_release_notes: false
body_path: artifacts/release-notes.md
name: OpenChamber v${{ steps.get_version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-desktop-macos:
needs: create-release
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: packages/desktop/src-tauri
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Apple Certificate
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
# Create temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Import certificate
echo "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12
security import $RUNNER_TEMP/certificate.p12 \
-P "$APPLE_CERTIFICATE_PASSWORD" \
-A -t cert -f pkcs12 \
-k "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple:,codesign: \
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
- name: Set up notarization credentials
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
run: |
# Validate secrets are set
if [ -z "$APPLE_ID" ] || [ -z "$APPLE_TEAM_ID" ] || [ -z "$APPLE_PASSWORD" ]; then
echo "Error: Missing Apple notarization credentials"
exit 1
fi
xcrun notarytool store-credentials "openchamber-notarize" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_PASSWORD"
- name: Build UI package
run: pnpm -C packages/ui run build
- name: Build Desktop app
run: pnpm desktop:build
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_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 }}
- name: Prepare release artifacts
run: |
mkdir -p artifacts
VERSION="${{ needs.create-release.outputs.version }}"
# Copy DMG
cp packages/desktop/src-tauri/target/release/bundle/dmg/*.dmg artifacts/ 2>/dev/null || true
# Copy tar.gz and signature for updater
cp packages/desktop/src-tauri/target/release/bundle/macos/*.tar.gz artifacts/ 2>/dev/null || true
cp packages/desktop/src-tauri/target/release/bundle/macos/*.tar.gz.sig artifacts/ 2>/dev/null || true
- name: Generate update manifest
run: |
VERSION="${{ needs.create-release.outputs.version }}"
# Find the signature file
SIG_FILE=$(find artifacts -name "*.tar.gz.sig" | head -1)
if [ -f "$SIG_FILE" ]; then
SIGNATURE=$(cat "$SIG_FILE")
else
SIGNATURE=""
fi
# Find the tar.gz file name
TAR_FILE=$(find artifacts -name "*.tar.gz" ! -name "*.sig" | head -1)
TAR_NAME=$(basename "$TAR_FILE" 2>/dev/null || echo "OpenChamber.app.tar.gz")
cat > artifacts/latest.json << EOF
{
"version": "${VERSION}",
"notes": "See release notes at https://github.com/${{ github.repository }}/releases/tag/v${VERSION}",
"pub_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"platforms": {
"darwin-aarch64": {
"signature": "${SIGNATURE}",
"url": "https://github.com/${{ github.repository }}/releases/download/v${VERSION}/${TAR_NAME}"
}
}
}
EOF
echo "Generated latest.json:"
cat artifacts/latest.json
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
files: |
artifacts/*.dmg
artifacts/*.tar.gz
artifacts/*.tar.gz.sig
artifacts/latest.json
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-npm:
needs: create-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages
run: pnpm run build
- name: Create npm tarball
working-directory: packages/web
run: npm pack
- name: Upload npm tarball to release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
files: packages/web/*.tgz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to npm
if: ${{ github.event.inputs.dry_run != 'true' }}
working-directory: packages/web
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
finalize-release:
needs: [create-release, build-desktop-macos, publish-npm]
runs-on: ubuntu-latest
steps:
- name: Publish release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
draft: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}