858 lines
30 KiB
YAML
858 lines
30 KiB
YAML
name: Build and Upload Binaries
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
ref:
|
|
description: "Git ref (branch, tag, or SHA) to build from"
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
version:
|
|
description: "Version to apply to workspace packages (release builds)"
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
tag:
|
|
description: "Git tag to upload assets to (release builds)"
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
release_name:
|
|
description: "Release name (unused here, for context)"
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
upload:
|
|
description: "Upload built artifacts to the GitHub release"
|
|
required: false
|
|
default: true
|
|
type: boolean
|
|
upload_actions_artifacts:
|
|
description: "Upload built artifacts to GitHub Actions run artifacts"
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
actions_artifacts_retention_days:
|
|
description: "Retention (days) for GitHub Actions artifacts"
|
|
required: false
|
|
default: 7
|
|
type: number
|
|
actions_artifacts_name_prefix:
|
|
description: "Optional prefix for Actions artifact names"
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
set_versions:
|
|
description: "Run npm version to set workspace versions"
|
|
required: false
|
|
default: true
|
|
type: boolean
|
|
|
|
# Permissions are intentionally omitted here so callers can choose
|
|
# least-privilege (e.g. dev CI uses read-only; releases grant write).
|
|
|
|
env:
|
|
NODE_VERSION: 20
|
|
|
|
jobs:
|
|
build-macos:
|
|
runs-on: macos-15-intel
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
shell: bash
|
|
env:
|
|
NPM_CONFIG_FETCH_RETRIES: 5
|
|
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT: 20000
|
|
NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT: 120000
|
|
run: |
|
|
set -euo pipefail
|
|
for attempt in 1 2 3; do
|
|
if npm version "${VERSION}" --workspaces --include-workspace-root --no-git-tag-version --allow-same-version; then
|
|
exit 0
|
|
fi
|
|
echo "npm version failed (attempt $attempt/3); retrying..." >&2
|
|
sleep $((attempt * 10))
|
|
done
|
|
exit 1
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-darwin-x64 --no-save
|
|
|
|
- name: Build macOS binaries (Electron)
|
|
run: npm run build:mac --workspace @neuralnomads/codenomad-electron-app
|
|
|
|
- name: Ad-hoc sign Electron macOS app bundles (seal resources)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
release_root="packages/electron-app/release"
|
|
apps=()
|
|
while IFS= read -r -d '' app; do
|
|
apps+=("$app")
|
|
done < <(find "$release_root" -type d -name 'CodeNomad.app' -print0)
|
|
|
|
if [ "${#apps[@]}" -eq 0 ]; then
|
|
echo "No CodeNomad.app found under $release_root" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# GitHub macOS runners typically have no signing identity. Without any signature,
|
|
# the shipped .app can fail Gatekeeper with:
|
|
# code has no resources but signature indicates they must be present
|
|
# Ad-hoc signing seals bundle resources and makes the signature internally consistent.
|
|
if security find-identity -p codesigning -v | grep -q "0 valid identities found"; then
|
|
echo "No valid macOS codesigning identity found; applying ad-hoc signature"
|
|
for app in "${apps[@]}"; do
|
|
echo "codesign (adhoc): $app"
|
|
codesign --force --deep --sign - "$app"
|
|
codesign --verify --deep --strict --verbose=2 "$app"
|
|
done
|
|
else
|
|
echo "macOS codesigning identity present; skipping ad-hoc signing"
|
|
fi
|
|
|
|
- name: Repackage Electron macOS zips (ditto)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# Prefer the workflow-provided version; fall back to package.json.
|
|
VERSION_TO_USE="${VERSION:-}"
|
|
if [ -z "$VERSION_TO_USE" ]; then
|
|
VERSION_TO_USE=$(node -p "require('./packages/electron-app/package.json').version")
|
|
fi
|
|
|
|
release_root="packages/electron-app/release"
|
|
# macOS GitHub runners ship /bin/bash 3.2 which doesn't support `shopt -s globstar`.
|
|
# Use find to locate built app bundles instead of ** globs.
|
|
apps=()
|
|
while IFS= read -r -d '' app; do
|
|
apps+=("$app")
|
|
done < <(find "$release_root" -type d -name 'CodeNomad.app' -print0)
|
|
if [ "${#apps[@]}" -eq 0 ]; then
|
|
echo "No CodeNomad.app found under $release_root" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for app in "${apps[@]}"; do
|
|
bundle_dir=$(basename "$(dirname "$app")")
|
|
arch="x64"
|
|
if [[ "$bundle_dir" == *"arm64"* ]]; then
|
|
arch="arm64"
|
|
fi
|
|
|
|
out_zip="$release_root/CodeNomad-${VERSION_TO_USE}-mac-${arch}.zip"
|
|
rm -f "$out_zip"
|
|
echo "ditto -ck: $app -> $out_zip"
|
|
ditto -ck --sequesterRsrc --keepParent "$app" "$out_zip"
|
|
done
|
|
|
|
- name: Validate Electron macOS codesign (unzipped)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
|
|
tmp_dir=$(mktemp -d)
|
|
trap 'rm -rf "$tmp_dir"' EXIT
|
|
|
|
zips=(packages/electron-app/release/CodeNomad-*-mac-*.zip)
|
|
if [ "${#zips[@]}" -eq 0 ]; then
|
|
echo "No Electron macOS zip artifacts found to validate" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for zip in "${zips[@]}"; do
|
|
echo "Validating codesign for: $zip"
|
|
extract_dir="$tmp_dir/$(basename "$zip" .zip)"
|
|
mkdir -p "$extract_dir"
|
|
|
|
# Use ditto for extraction as well to preserve bundle metadata.
|
|
ditto -x -k "$zip" "$extract_dir"
|
|
|
|
app_path=""
|
|
for candidate in "$extract_dir"/*.app "$extract_dir"/*/*.app; do
|
|
if [ -d "$candidate" ]; then
|
|
app_path="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -z "$app_path" ]; then
|
|
echo "No .app found after extracting $zip" >&2
|
|
exit 1
|
|
fi
|
|
|
|
codesign --verify --deep --strict --verbose=2 "$app_path"
|
|
done
|
|
|
|
- name: Upload release assets
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
for file in packages/electron-app/release/*.zip packages/electron-app/release/*.AppImage; do
|
|
[ -f "$file" ] || continue
|
|
echo "Uploading $file"
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
- name: Upload Actions artifacts (Electron macOS)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}electron-macos
|
|
path: packages/electron-app/release/*.zip
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: error
|
|
|
|
build-windows:
|
|
runs-on: windows-2025
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
run: npm version ${{ env.VERSION }} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
shell: bash
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-win32-x64-msvc --no-save
|
|
|
|
- name: Build Windows binaries (Electron)
|
|
run: npm run build:win --workspace @neuralnomads/codenomad-electron-app
|
|
|
|
- name: Upload release assets
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
shell: pwsh
|
|
run: |
|
|
Get-ChildItem -Path "packages/electron-app/release" -Filter *.zip -File | ForEach-Object {
|
|
Write-Host "Uploading $($_.FullName)"
|
|
gh release upload $env:TAG $_.FullName --clobber
|
|
}
|
|
|
|
- name: Upload Actions artifacts (Electron Windows)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}electron-windows
|
|
path: packages/electron-app/release/*.zip
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: error
|
|
|
|
build-linux:
|
|
runs-on: ubuntu-24.04
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-linux-x64-gnu --no-save
|
|
|
|
- name: Build Linux binaries (Electron)
|
|
run: npm run build:linux --workspace @neuralnomads/codenomad-electron-app
|
|
|
|
- name: Upload release assets
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
for file in packages/electron-app/release/*.zip packages/electron-app/release/*.AppImage; do
|
|
[ -f "$file" ] || continue
|
|
echo "Uploading $file"
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
- name: Upload Actions artifacts (Electron Linux)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}electron-linux
|
|
path: |
|
|
packages/electron-app/release/*.zip
|
|
packages/electron-app/release/*.AppImage
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: error
|
|
|
|
build-tauri-macos:
|
|
runs-on: macos-15-intel
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Setup Rust (Tauri)
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-darwin-x64 --no-save
|
|
|
|
- name: Prebuild (Tauri)
|
|
run: npm run prebuild --workspace @codenomad/tauri-app
|
|
|
|
- name: Ensure tauri native binary
|
|
working-directory: packages/tauri-app
|
|
run: |
|
|
set -euo pipefail
|
|
for attempt in 1 2 3; do
|
|
if [ "$attempt" -gt 1 ]; then
|
|
echo "Retrying Tauri CLI install (attempt $attempt)..."
|
|
fi
|
|
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-darwin-x64@2.9.4 --no-save --no-audit --no-fund --workspaces=false
|
|
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
|
|
done
|
|
echo "Tauri CLI failed to load after retries" >&2
|
|
exit 1
|
|
|
|
- name: Build macOS bundle (Tauri)
|
|
working-directory: packages/tauri-app
|
|
run: npm exec -- tauri build
|
|
|
|
- name: Package Tauri artifacts (macOS)
|
|
if: ${{ inputs.upload || inputs.upload_actions_artifacts }}
|
|
run: |
|
|
set -euo pipefail
|
|
BUNDLE_ROOT="packages/tauri-app/target/release/bundle"
|
|
ARTIFACT_DIR="packages/tauri-app/release-tauri"
|
|
rm -rf "$ARTIFACT_DIR"
|
|
mkdir -p "$ARTIFACT_DIR"
|
|
if [ -d "$BUNDLE_ROOT/macos/CodeNomad.app" ]; then
|
|
ditto -ck --sequesterRsrc --keepParent "$BUNDLE_ROOT/macos/CodeNomad.app" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-macos-x64.zip"
|
|
fi
|
|
|
|
- name: Upload Actions artifacts (Tauri macOS)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}tauri-macos
|
|
path: packages/tauri-app/release-tauri/*.zip
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: warn
|
|
|
|
- name: Upload Tauri release assets (macOS)
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
for file in packages/tauri-app/release-tauri/*.zip; do
|
|
[ -f "$file" ] || continue
|
|
echo "Uploading $file"
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
build-tauri-macos-arm64:
|
|
runs-on: macos-26
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Setup Rust (Tauri)
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-darwin-arm64 --no-save
|
|
|
|
- name: Prebuild (Tauri)
|
|
run: npm run prebuild --workspace @codenomad/tauri-app
|
|
|
|
- name: Ensure tauri native binary
|
|
working-directory: packages/tauri-app
|
|
run: |
|
|
set -euo pipefail
|
|
for attempt in 1 2 3; do
|
|
if [ "$attempt" -gt 1 ]; then
|
|
echo "Retrying Tauri CLI install (attempt $attempt)..."
|
|
fi
|
|
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-darwin-arm64@2.9.4 --no-save --no-audit --no-fund --workspaces=false
|
|
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
|
|
done
|
|
echo "Tauri CLI failed to load after retries" >&2
|
|
exit 1
|
|
|
|
- name: Build macOS bundle (Tauri, arm64)
|
|
working-directory: packages/tauri-app
|
|
run: npm exec -- tauri build
|
|
|
|
- name: Package Tauri artifacts (macOS arm64)
|
|
if: ${{ inputs.upload || inputs.upload_actions_artifacts }}
|
|
run: |
|
|
set -euo pipefail
|
|
BUNDLE_ROOT="packages/tauri-app/target/release/bundle"
|
|
ARTIFACT_DIR="packages/tauri-app/release-tauri"
|
|
rm -rf "$ARTIFACT_DIR"
|
|
mkdir -p "$ARTIFACT_DIR"
|
|
if [ -d "$BUNDLE_ROOT/macos/CodeNomad.app" ]; then
|
|
ditto -ck --sequesterRsrc --keepParent "$BUNDLE_ROOT/macos/CodeNomad.app" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-macos-arm64.zip"
|
|
fi
|
|
|
|
- name: Upload Actions artifacts (Tauri macOS arm64)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}tauri-macos-arm64
|
|
path: packages/tauri-app/release-tauri/*.zip
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: warn
|
|
|
|
- name: Upload Tauri release assets (macOS arm64)
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
for file in packages/tauri-app/release-tauri/*.zip; do
|
|
[ -f "$file" ] || continue
|
|
echo "Uploading $file"
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
build-tauri-windows:
|
|
runs-on: windows-2025
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Setup Rust (Tauri)
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
run: npm version ${{ env.VERSION }} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
shell: bash
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-win32-x64-msvc --no-save
|
|
|
|
- name: Prebuild (Tauri)
|
|
run: npm run prebuild --workspace @codenomad/tauri-app
|
|
|
|
- name: Ensure tauri native binary
|
|
shell: bash
|
|
working-directory: packages/tauri-app
|
|
run: |
|
|
set -euo pipefail
|
|
for attempt in 1 2 3; do
|
|
if [ "$attempt" -gt 1 ]; then
|
|
echo "Retrying Tauri CLI install (attempt $attempt)..."
|
|
fi
|
|
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-win32-x64-msvc@2.9.4 --no-save --no-audit --no-fund --workspaces=false
|
|
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
|
|
done
|
|
echo "Tauri CLI failed to load after retries" >&2
|
|
exit 1
|
|
|
|
- name: Build Windows bundle (Tauri)
|
|
shell: bash
|
|
working-directory: packages/tauri-app
|
|
run: npm exec -- tauri build
|
|
|
|
- name: Package Tauri artifacts (Windows)
|
|
if: ${{ inputs.upload || inputs.upload_actions_artifacts }}
|
|
shell: pwsh
|
|
run: |
|
|
$bundleRoot = "packages/tauri-app/target/release/bundle"
|
|
$artifactDir = "packages/tauri-app/release-tauri"
|
|
if (Test-Path $artifactDir) { Remove-Item $artifactDir -Recurse -Force }
|
|
New-Item -ItemType Directory -Path $artifactDir | Out-Null
|
|
$exe = Get-ChildItem -Path $bundleRoot -Recurse -File -Filter *.exe | Select-Object -First 1
|
|
if ($null -ne $exe) {
|
|
$dest = Join-Path $artifactDir ("CodeNomad-Tauri-$env:VERSION-windows-x64.zip")
|
|
Compress-Archive -Path $exe.Directory.FullName -DestinationPath $dest -Force
|
|
}
|
|
|
|
- name: Upload Actions artifacts (Tauri Windows)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}tauri-windows
|
|
path: packages/tauri-app/release-tauri/*.zip
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: warn
|
|
|
|
- name: Upload Tauri release assets (Windows)
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
shell: pwsh
|
|
run: |
|
|
if (Test-Path "packages/tauri-app/release-tauri") {
|
|
Get-ChildItem -Path "packages/tauri-app/release-tauri" -Filter *.zip -File | ForEach-Object {
|
|
Write-Host "Uploading $($_.FullName)"
|
|
gh release upload $env:TAG $_.FullName --clobber
|
|
}
|
|
}
|
|
|
|
build-tauri-linux:
|
|
runs-on: ubuntu-24.04
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Setup Rust (Tauri)
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Install Linux build dependencies (Tauri)
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
build-essential \
|
|
pkg-config \
|
|
libgtk-3-dev \
|
|
libglib2.0-dev \
|
|
libwebkit2gtk-4.1-dev \
|
|
libsoup-3.0-dev \
|
|
libayatana-appindicator3-dev \
|
|
librsvg2-dev
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-linux-x64-gnu --no-save
|
|
|
|
- name: Prebuild (Tauri)
|
|
run: npm run prebuild --workspace @codenomad/tauri-app
|
|
|
|
- name: Ensure tauri native binary
|
|
working-directory: packages/tauri-app
|
|
run: |
|
|
set -euo pipefail
|
|
for attempt in 1 2 3; do
|
|
if [ "$attempt" -gt 1 ]; then
|
|
echo "Retrying Tauri CLI install (attempt $attempt)..."
|
|
fi
|
|
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-linux-x64-gnu@2.9.4 --no-save --no-audit --no-fund --workspaces=false
|
|
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
|
|
done
|
|
echo "Tauri CLI failed to load after retries" >&2
|
|
exit 1
|
|
|
|
- name: Build Linux bundle (Tauri)
|
|
working-directory: packages/tauri-app
|
|
run: npm exec -- tauri build
|
|
|
|
- name: Package Tauri artifacts (Linux)
|
|
if: ${{ inputs.upload || inputs.upload_actions_artifacts }}
|
|
run: |
|
|
set -euo pipefail
|
|
SEARCH_ROOT="packages/tauri-app/target"
|
|
ARTIFACT_DIR="packages/tauri-app/release-tauri"
|
|
rm -rf "$ARTIFACT_DIR"
|
|
mkdir -p "$ARTIFACT_DIR"
|
|
shopt -s nullglob globstar
|
|
|
|
find_one() {
|
|
find "$SEARCH_ROOT" -type f -iname "$1" | head -n1
|
|
}
|
|
|
|
appimage=$(find_one "*.AppImage")
|
|
deb=$(find_one "*.deb")
|
|
rpm=$(find_one "*.rpm")
|
|
|
|
if [ -z "$appimage" ] || [ -z "$deb" ] || [ -z "$rpm" ]; then
|
|
echo "Missing bundle(s): appimage=${appimage:-none} deb=${deb:-none} rpm=${rpm:-none}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cp "$appimage" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.AppImage"
|
|
cp "$deb" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.deb"
|
|
cp "$rpm" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.rpm"
|
|
|
|
- name: Upload Actions artifacts (Tauri Linux)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}tauri-linux
|
|
path: packages/tauri-app/release-tauri/*
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: warn
|
|
|
|
- name: Upload Tauri release assets (Linux)
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
for file in packages/tauri-app/release-tauri/*; do
|
|
[ -f "$file" ] || continue
|
|
echo "Uploading $file"
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
build-tauri-linux-arm64:
|
|
if: ${{ false }}
|
|
runs-on: ubuntu-24.04
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup QEMU
|
|
uses: docker/setup-qemu-action@v3
|
|
with:
|
|
platforms: linux/arm64
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Setup Rust (Tauri)
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: aarch64-unknown-linux-gnu
|
|
|
|
- name: Install Linux build dependencies (Tauri)
|
|
run: |
|
|
sudo dpkg --add-architecture arm64
|
|
sudo tee /etc/apt/sources.list.d/arm64.list >/dev/null <<'EOF'
|
|
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse
|
|
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse
|
|
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse
|
|
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-backports main restricted universe multiverse
|
|
EOF
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
build-essential \
|
|
pkg-config \
|
|
gcc-aarch64-linux-gnu \
|
|
g++-aarch64-linux-gnu \
|
|
libgtk-3-dev:arm64 \
|
|
libglib2.0-dev:arm64 \
|
|
libwebkit2gtk-4.1-dev:arm64 \
|
|
libsoup-3.0-dev:arm64 \
|
|
libayatana-appindicator3-dev:arm64 \
|
|
librsvg2-dev:arm64
|
|
|
|
- name: Set workspace versions
|
|
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-linux-arm64-gnu --no-save
|
|
|
|
- name: Build Linux bundle (Tauri arm64)
|
|
env:
|
|
TAURI_BUILD_TARGET: aarch64-unknown-linux-gnu
|
|
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
|
|
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
|
|
CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++
|
|
AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-ar
|
|
run: npm run build --workspace @codenomad/tauri-app
|
|
|
|
- name: Package Tauri artifacts (Linux arm64)
|
|
run: |
|
|
set -euo pipefail
|
|
SEARCH_ROOT="packages/tauri-app/target"
|
|
ARTIFACT_DIR="packages/tauri-app/release-tauri"
|
|
rm -rf "$ARTIFACT_DIR"
|
|
mkdir -p "$ARTIFACT_DIR"
|
|
shopt -s nullglob globstar
|
|
first_artifact=$(find "$SEARCH_ROOT" -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" -o -name "*.tar.gz" \) | head -n1)
|
|
fallback_bin="$SEARCH_ROOT/release/codenomad-tauri"
|
|
if [ -n "$first_artifact" ]; then
|
|
zip -j "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.zip" "$first_artifact"
|
|
elif [ -f "$fallback_bin" ]; then
|
|
zip -j "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.zip" "$fallback_bin"
|
|
else
|
|
echo "No bundled artifact found under $SEARCH_ROOT and no binary at $fallback_bin" >&2
|
|
exit 1
|
|
fi
|
|
|
|
|
|
- name: Upload Tauri release assets (Linux arm64)
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
for file in packages/tauri-app/release-tauri/*.zip; do
|
|
[ -f "$file" ] || continue
|
|
echo "Uploading $file"
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
|
|
build-linux-rpm:
|
|
runs-on: ubuntu-24.04
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION: ${{ inputs.version }}
|
|
TAG: ${{ inputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.ref || github.ref }}
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: npm
|
|
|
|
- name: Install rpm packaging dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y rpm ruby ruby-dev build-essential
|
|
sudo gem install --no-document fpm
|
|
|
|
- name: Set workspace versions
|
|
if: ${{ inputs.set_versions && inputs.version != '' }}
|
|
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
|
|
|
|
- name: Install project dependencies
|
|
run: npm ci --workspaces --include=optional
|
|
|
|
- name: Ensure rollup native binary
|
|
run: npm install @rollup/rollup-linux-x64-gnu --no-save
|
|
|
|
- name: Build Linux RPM binaries
|
|
run: npm run build:linux-rpm --workspace @neuralnomads/codenomad-electron-app
|
|
|
|
- name: Upload RPM release assets
|
|
if: ${{ inputs.upload && inputs.tag != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
for file in packages/electron-app/release/*.rpm; do
|
|
[ -f "$file" ] || continue
|
|
echo "Uploading $file"
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
- name: Upload Actions artifacts (Electron Linux RPM)
|
|
if: ${{ inputs.upload_actions_artifacts }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ inputs.actions_artifacts_name_prefix }}electron-linux-rpm
|
|
path: packages/electron-app/release/*.rpm
|
|
retention-days: ${{ inputs.actions_artifacts_retention_days }}
|
|
if-no-files-found: error
|