Skip to content

chore(release): 0.27.1 #68

chore(release): 0.27.1

chore(release): 0.27.1 #68

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write
jobs:
build-sdist:
name: Build sdists
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Build review app frontend
working-directory: web/review-app
run: npm ci && npm run build
- name: Build terminal app frontend
working-directory: web/terminal-app
run: npm ci && npm run build
- name: Build markdown preview app frontend
working-directory: web/markdown-app
run: npm ci && npm run build
- name: Build VNC app frontend
working-directory: web/vnc-app
run: npm ci && npm run build
- name: Build config app frontend
working-directory: web/config-app
run: npm ci && npm run build
- name: Build open-shrimp sdist
run: uv build --sdist
- name: Build moonshine-stt sdist
working-directory: moonshine-stt
run: uv build --sdist
- name: Upload open-shrimp sdist
uses: actions/upload-artifact@v7
with:
name: sdist-openshrimp
path: dist/*.tar.gz
- name: Upload moonshine-stt sdist
uses: actions/upload-artifact@v7
with:
name: sdist-moonshine-stt
path: moonshine-stt/dist/*.tar.gz
build-binary:
name: Build ${{ matrix.artifact }}
needs: build-sdist
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# open-shrimp
- os: ubuntu-latest
artifact: openshrimp-linux-x86_64
sdist_artifact: sdist-openshrimp
exec_code: "from open_shrimp.main import main; main()"
features: "libvirt"
- os: ubuntu-24.04-arm
artifact: openshrimp-linux-aarch64
sdist_artifact: sdist-openshrimp
exec_code: "from open_shrimp.main import main; main()"
features: "libvirt"
- os: macos-latest
artifact: openshrimp-macos-aarch64
sdist_artifact: sdist-openshrimp
exec_code: "from open_shrimp.main import main; main()"
- os: macos-latest
artifact: openshrimp-macos-x86_64
sdist_artifact: sdist-openshrimp
exec_code: "from open_shrimp.main import main; main()"
rust_target: x86_64-apple-darwin
# moonshine-stt
- os: ubuntu-latest
artifact: moonshine-stt-linux-x86_64
sdist_artifact: sdist-moonshine-stt
exec_code: "from moonshine_stt.main import main; main()"
- os: ubuntu-24.04-arm
artifact: moonshine-stt-linux-aarch64
sdist_artifact: sdist-moonshine-stt
exec_code: "from moonshine_stt.main import main; main()"
- os: macos-latest
artifact: moonshine-stt-macos-aarch64
sdist_artifact: sdist-moonshine-stt
exec_code: "from moonshine_stt.main import main; main()"
- os: macos-latest
artifact: moonshine-stt-macos-x86_64
sdist_artifact: sdist-moonshine-stt
exec_code: "from moonshine_stt.main import main; main()"
rust_target: x86_64-apple-darwin
steps:
- uses: actions/checkout@v6
- name: Download sdist
uses: actions/download-artifact@v8
with:
name: ${{ matrix.sdist_artifact }}
path: dist
- name: Install libvirt development headers
if: matrix.features && contains(matrix.features, 'libvirt')
run: sudo apt-get update && sudo apt-get install -y libvirt-dev
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target || '' }}
- name: Cache Cargo registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-pyapp-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-pyapp-
- name: Get sdist filename
id: sdist
run: echo "filename=$(realpath dist/*.tar.gz)" >> "$GITHUB_OUTPUT"
- name: Build with PyApp
env:
PYAPP_PROJECT_PATH: ${{ steps.sdist.outputs.filename }}
PYAPP_PROJECT_FEATURES: ${{ matrix.features || '' }}
PYAPP_PYTHON_VERSION: "3.11"
PYAPP_EXEC_CODE: ${{ matrix.exec_code }}
PYAPP_DISTRIBUTION_EMBED: "1"
PYAPP_PASS_LOCATION: "1"
run: |
if [ -n "${{ matrix.rust_target }}" ]; then
cargo install pyapp --force --root dist/pyapp --target ${{ matrix.rust_target }}
else
cargo install pyapp --force --root dist/pyapp
fi
- name: Rename binary
run: mv dist/pyapp/bin/pyapp dist/${{ matrix.artifact }}
- name: Import signing certificate
if: runner.os == 'macOS'
env:
CERT_B64: ${{ secrets.MACOS_CERTIFICATE_P12_BASE64 }}
CERT_PW: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
KC_PW: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
run: |
KC="$RUNNER_TEMP/build.keychain-db"
echo -n "$CERT_B64" | base64 --decode -o "$RUNNER_TEMP/cert.p12"
security create-keychain -p "$KC_PW" "$KC"
security set-keychain-settings -lut 21600 "$KC"
security unlock-keychain -p "$KC_PW" "$KC"
security import "$RUNNER_TEMP/cert.p12" -k "$KC" -P "$CERT_PW" \
-T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KC_PW" "$KC"
security list-keychains -d user -s "$KC" $(security list-keychains -d user | tr -d '"')
rm "$RUNNER_TEMP/cert.p12"
- name: Sign and notarize binary
if: runner.os == 'macOS'
env:
IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
API_KEY_B64: ${{ secrets.MACOS_NOTARY_API_KEY_P8_BASE64 }}
API_KEY_ID: ${{ secrets.MACOS_NOTARY_API_KEY_ID }}
API_ISSUER_ID: ${{ secrets.MACOS_NOTARY_API_ISSUER_ID }}
run: |
set -e
BIN="dist/${{ matrix.artifact }}"
codesign --force --timestamp --options runtime \
--entitlements entitlements.plist \
--sign "$IDENTITY" "$BIN"
codesign --verify --strict --verbose=2 "$BIN"
KEY="$RUNNER_TEMP/notary_key.p8"
echo -n "$API_KEY_B64" | base64 --decode -o "$KEY"
ZIP="$RUNNER_TEMP/${{ matrix.artifact }}.zip"
ditto -c -k --keepParent "$BIN" "$ZIP"
set +e
SUBMIT_OUT=$(xcrun notarytool submit "$ZIP" \
--key "$KEY" --key-id "$API_KEY_ID" --issuer "$API_ISSUER_ID" \
--wait --timeout 30m 2>&1)
SUBMIT_RC=$?
echo "$SUBMIT_OUT"
SUBMIT_ID=$(printf '%s\n' "$SUBMIT_OUT" | awk '/^[[:space:]]*id:/ {print $2; exit}')
if [ "$SUBMIT_RC" -ne 0 ] || ! printf '%s\n' "$SUBMIT_OUT" | grep -q 'status: Accepted'; then
if [ -n "$SUBMIT_ID" ]; then
echo "::group::Notary log for $SUBMIT_ID"
xcrun notarytool log "$SUBMIT_ID" \
--key "$KEY" --key-id "$API_KEY_ID" --issuer "$API_ISSUER_ID" || true
echo "::endgroup::"
fi
rm -f "$ZIP" "$KEY"
exit 1
fi
# Single-file binaries can't be stapled; Gatekeeper checks online.
rm "$ZIP" "$KEY"
- name: Upload binary
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.artifact }}
path: dist/${{ matrix.artifact }}
build-virtiofsd:
name: Build virtiofsd (${{ matrix.arch }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
arch: x86_64
artifact: virtiofsd-linux-x86_64
- os: ubuntu-24.04-arm
arch: aarch64
artifact: virtiofsd-linux-aarch64
steps:
- name: Install system build dependencies
run: sudo apt-get update && sudo apt-get install -y libseccomp-dev libcap-ng-dev
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-${{ runner.arch }}-cargo-virtiofsd-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-cargo-virtiofsd-
- name: Clone virtiofsd
run: git clone --depth 1 --branch v1.13.3 https://gitlab.com/virtio-fs/virtiofsd.git
- name: Build virtiofsd
working-directory: virtiofsd
run: cargo build --release
- name: Rename binary
run: mv virtiofsd/target/release/virtiofsd ${{ matrix.artifact }}
- name: Upload binary
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.artifact }}
path: ${{ matrix.artifact }}
build-macos-app:
name: Build macOS .app
needs: build-sdist
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Build review app frontend
working-directory: web/review-app
run: npm ci && npm run build
- name: Build terminal app frontend
working-directory: web/terminal-app
run: npm ci && npm run build
- name: Build markdown preview app frontend
working-directory: web/markdown-app
run: npm ci && npm run build
- name: Build VNC app frontend
working-directory: web/vnc-app
run: npm ci && npm run build
- name: Build config app frontend
working-directory: web/config-app
run: npm ci && npm run build
- name: Install dependencies
run: |
uv pip install --system py2app setuptools
uv pip install --system '.[macos]'
- name: Build .app bundle
run: |
# ruamel is a PEP 420 namespace package (no __init__.py), which
# py2app's imp.find_module cannot resolve. Add a stub so py2app
# can locate the package.
touch "$(python -c 'import ruamel; print(ruamel.__path__[0])')/__init__.py"
mv pyproject.toml pyproject.toml.bak
python setup_app.py py2app
mv pyproject.toml.bak pyproject.toml
- name: Import signing certificate
env:
CERT_B64: ${{ secrets.MACOS_CERTIFICATE_P12_BASE64 }}
CERT_PW: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
KC_PW: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
run: |
KC="$RUNNER_TEMP/build.keychain-db"
echo -n "$CERT_B64" | base64 --decode -o "$RUNNER_TEMP/cert.p12"
security create-keychain -p "$KC_PW" "$KC"
security set-keychain-settings -lut 21600 "$KC"
security unlock-keychain -p "$KC_PW" "$KC"
security import "$RUNNER_TEMP/cert.p12" -k "$KC" -P "$CERT_PW" \
-T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KC_PW" "$KC"
security list-keychains -d user -s "$KC" $(security list-keychains -d user | tr -d '"')
rm "$RUNNER_TEMP/cert.p12"
- name: Sign .app bundle
env:
IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
run: |
set -e
APP="dist/OpenShrimp.app"
# Sign every Mach-O file inside the bundle. Extension-based matching
# isn't enough for py2app (the embedded Python interpreter has no
# suffix), so probe each file with `file`.
find "$APP" -type f | while read -r f; do
if file -b "$f" | grep -qE 'Mach-O|dynamically linked shared library'; then
codesign --force --timestamp --options runtime \
--sign "$IDENTITY" "$f"
fi
done
# Sign embedded bundles (frameworks, nested .app) deepest-first so
# each enclosing CodeResources seal covers already-signed contents.
find "$APP/Contents" -type d \( -name "*.framework" -o -name "*.app" \) | \
awk -F/ '{ print NF, $0 }' | sort -k1 -rn | cut -d' ' -f2- | \
while read -r b; do
codesign --force --timestamp --options runtime \
--sign "$IDENTITY" "$b"
done
# Finally sign the outer bundle with entitlements.
codesign --force --timestamp --options runtime \
--entitlements entitlements.plist \
--sign "$IDENTITY" "$APP"
codesign --verify --strict --deep --verbose=2 "$APP"
- name: Create DMG
run: |
brew install create-dmg
create-dmg \
--volname "OpenShrimp" \
--window-size 600 400 \
--icon "OpenShrimp.app" 150 200 \
--app-drop-link 450 200 \
--no-internet-enable \
"dist/OpenShrimp-$(cat VERSION).dmg" \
"dist/OpenShrimp.app"
- name: Sign, notarize, and staple DMG
env:
IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
API_KEY_B64: ${{ secrets.MACOS_NOTARY_API_KEY_P8_BASE64 }}
API_KEY_ID: ${{ secrets.MACOS_NOTARY_API_KEY_ID }}
API_ISSUER_ID: ${{ secrets.MACOS_NOTARY_API_ISSUER_ID }}
run: |
set -e
DMG="dist/OpenShrimp-$(cat VERSION).dmg"
codesign --force --timestamp --sign "$IDENTITY" "$DMG"
KEY="$RUNNER_TEMP/notary_key.p8"
echo -n "$API_KEY_B64" | base64 --decode -o "$KEY"
set +e
SUBMIT_OUT=$(xcrun notarytool submit "$DMG" \
--key "$KEY" --key-id "$API_KEY_ID" --issuer "$API_ISSUER_ID" \
--wait --timeout 30m 2>&1)
SUBMIT_RC=$?
echo "$SUBMIT_OUT"
SUBMIT_ID=$(printf '%s\n' "$SUBMIT_OUT" | awk '/^[[:space:]]*id:/ {print $2; exit}')
if [ "$SUBMIT_RC" -ne 0 ] || ! printf '%s\n' "$SUBMIT_OUT" | grep -q 'status: Accepted'; then
if [ -n "$SUBMIT_ID" ]; then
echo "::group::Notary log for $SUBMIT_ID"
xcrun notarytool log "$SUBMIT_ID" \
--key "$KEY" --key-id "$API_KEY_ID" --issuer "$API_ISSUER_ID" || true
echo "::endgroup::"
fi
rm -f "$KEY"
exit 1
fi
rm "$KEY"
xcrun stapler staple "$DMG"
xcrun stapler validate "$DMG"
- name: Upload DMG
uses: actions/upload-artifact@v7
with:
name: OpenShrimp-macos-app
path: dist/OpenShrimp-*.dmg
release:
name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
needs: [build-binary, build-virtiofsd, build-macos-app]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Download all artifacts
uses: actions/download-artifact@v8
with:
path: artifacts
merge-multiple: true
- name: Create release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
artifacts/openshrimp-*
artifacts/moonshine-stt-*
artifacts/virtiofsd-*
artifacts/OpenShrimp-*.dmg
artifacts/*.tar.gz