Files
ever-gauzy/.github/workflows/agent-demo.yml
T
Ruslan KonviserandClaude Opus 4.8 2c28fa70ae fix(desktop): retire dead DigitalOcean Spaces update CDN, default all installs to GitHub feed
The desktop update origin `ever.sfo3.cdn.digitaloceanspaces.com` died with the locked
DigitalOcean account (CDN host NXDOMAIN, origin bucket returns NoSuchBucket). Every shipped
Electron app defaulted to that dead feed and, on failure, had no fallback — so installs were
silently stranded with no path to a new version.

GitHub Releases is already a live, current feed (each app repo carries v111.0.12 with the
`latest*.yml` metadata electron-updater needs). This makes GitHub the default everywhere:

- packages/desktop-lib/src/lib/desktop-updater.ts: the active update strategy now defaults to
  GithubCdn (was DigitalOceanCdn). This is the load-bearing fix — apps that never call
  checkUpdate() explicitly (e.g. agent) rely solely on the automatic loop, which used the
  hardcoded DigitalOcean constructor default. The automatic loop now starts only after the
  GitHub strategy's async initialize() resolves its feed URL. The deprecated `digitalOcean`
  option in both the settings path and the change_update_strategy IPC now resolves to GitHub,
  so a persisted `digitalOcean: true` (the old shipped default) can no longer pin an install
  to the dead CDN. The DigitalOceanCdn class is retained (unused) for reversibility.
- packages/desktop-core/.../application-setting-store.service.ts: shipped default cdnUpdater
  flipped to { github: true, digitalOcean: false } so fresh installs seed the live feed.
- apps/{desktop,desktop-timer,server,server-api,agent,server-mcp}/src/package.json: removed the
  dead `spaces` publish provider (bucket "ever"/sfo3); the `github` provider remains, so
  `yarn build:desktop:*:release` no longer targets the dead bucket.
- .github/workflows/*: dropped the now-unused DO_KEY_ID/DO_SECRET_KEY env (86 pairs across 18
  app workflows) that fed the removed Spaces upload.

Note: already-installed apps persist their update-source setting in Electron userData, which
survives reinstalls — so this fix reaches new installs and manual reinstalls-over-existing-data
(the runtime change ignores the dead persisted flag), but cannot reach installs that can no
longer update at all. Those require the DO CDN to be revived or a manual reinstall.

Windows Authenticode signing (GHSA-j75p-23jm-f83g) remains open — it needs a certificate that
does not exist yet; build.win is deliberately left unchanged (adding publisherName without a
real signature would make electron-updater verification fail closed). Runtime update flow was
verified statically (no Electron runtime available locally); CI validates build/lint/typecheck.

Refs: knowledge/infrastructure/DESKTOP_SIGNING_HANDOFF_PROMPT.md (Task 1), issue #9753

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 01:12:10 +02:00

258 lines
11 KiB
YAML

name: Agent App Build Demo
# The packaged desktop & server demo apps are built ONLY when 'develop' is promoted to the
# 'local-apps' branch. The build version is resolved at build time
# (.scripts/bump-version-electron.js) from the release tag of the promoted commit (on HEAD, or on the merge parent for PR-merge promotions), which
# 'Release Demo' creates on every merge to 'develop'.
on:
push:
branches:
- local-apps
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-${{ github.workflow }}
cancel-in-progress: true
jobs:
check-release-tag:
# Only build when the promoted commit carries a release tag (the version stamped into the
# packages - see header comment). 'local-apps' is promoted from 'develop' either by
# fast-forwarding to the tagged 'develop' commit (tag on HEAD) or by merging the
# 'develop' -> 'local-apps' promotion PR (the tag then points at the merged
# 'develop' tip, HEAD^2). Retries absorb the short delay until 'Release Demo' tags
# the 'develop' commit.
runs-on: ${{ vars.RUNNER_LINUX_X64_4 || 'ubuntu-latest' }}
timeout-minutes: 30
permissions:
contents: read
outputs:
# The resolved vX.Y.Z release tag; the build jobs stamp exactly this version.
tag: ${{ steps.resolve.outputs.tag }}
steps:
- name: Check out Git repository
uses: actions/checkout@v5
with:
persist-credentials: false
# Depth 2 so HEAD^2 resolves on merge-commit promotions
fetch-depth: 2
- name: Verify a release tag points at the promoted commit
id: resolve
shell: bash
run: |
if [ "$GITHUB_REF_NAME" != "local-apps" ]; then
echo "::error::This workflow only releases from the 'local-apps' branch (got '$GITHUB_REF_NAME')."
exit 1
fi
HEAD_SHA=$(git rev-parse HEAD)
# Present only when the promotion PR was merged as a merge commit; the release tag
# then points at the merged 'develop' tip, not at the merge commit itself.
PARENT2_SHA=$(git rev-parse --verify --quiet 'HEAD^2' || true)
resolve_tag() {
# Highest vX.Y.Z tag pointing at $1 in the remote listing (peeled '^{}' entries
# carry the commit sha of annotated tags); empty when none match.
printf '%s\n' "$REMOTE_REFS" | awk -v sha="$1" '
$1 == sha && $2 ~ /^refs\/tags\/v[0-9]+\.[0-9]+\.[0-9]+(\^\{\})?$/ {
t = $2
sub(/^refs\/tags\//, "", t)
sub(/\^\{\}$/, "", t)
print t
}' | sort -V | tail -n 1
}
for i in $(seq 1 20); do
if REMOTE_REFS=$(git ls-remote origin refs/heads/develop 'refs/tags/*'); then
SRC_TIP=$(printf '%s\n' "$REMOTE_REFS" | awk -v ref="refs/heads/develop" '$2 == ref { print $1 }')
TAG=$(resolve_tag "$HEAD_SHA")
# Accept the merge-parent tag only when HEAD^2 is the current 'develop' tip -
# i.e. this is the promotion merge of 'develop', not an arbitrary tagged branch
# merged in, nor a fast-forward racing 'Release Demo' (whose tag lands on HEAD).
if [ -z "$TAG" ] && [ -n "$PARENT2_SHA" ] && [ "$PARENT2_SHA" = "$SRC_TIP" ]; then
TAG=$(resolve_tag "$PARENT2_SHA")
fi
if [ -n "$TAG" ]; then
echo "Release tag on the promoted commit: $TAG"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
exit 0
fi
else
echo "git ls-remote failed (attempt $i); will retry"
fi
echo "No release tag points at this commit or its merge parent yet (attempt $i/20); retrying in 30s..."
sleep 30
done
echo "::error::No release tag points at this commit, and its merge parent does not match the tagged 'develop' tip. Promote by merging the 'develop' -> 'local-apps' PR (or fast-forwarding: git push origin origin/develop:local-apps) after 'Release Demo' has created the tag; if 'develop' has moved since the promotion PR was opened, re-promote."
exit 1
release-windows:
needs: check-release-tag
runs-on: ${{ matrix.os }}
timeout-minutes: 300
strategy:
matrix:
os: [[self-hosted, Windows, X64]]
steps:
- name: Check out Git repository
uses: actions/checkout@v5
with:
clean: false
- name: Selective cleanup (preserve .nx/cache)
shell: powershell
run: |
$ErrorActionPreference = 'SilentlyContinue'
# Stop NX daemon first to release file locks before cleanup (guard for fresh runners without Node)
if (Get-Command npx -ErrorAction SilentlyContinue) { npx nx daemon --stop 2>&1 | Out-Null }
# Remove build artifacts but keep NX cache for faster rebuilds
if (Test-Path "dist") { Remove-Item -Recurse -Force "dist" }
if (Test-Path "node_modules") { Remove-Item -Recurse -Force "node_modules" }
exit 0
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v6
with:
node-version: 24.17.0
- name: Install Visual Studio 2022 Build Tools (VCTools)
shell: powershell
run: |
choco install -y visualstudio2022buildtools --execution-timeout=21600 --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --includeOptional --passive --norestart"
- name: Configure node-gyp to use VS 2022
shell: powershell
run: |
"GYP_MSVS_VERSION=2022" | Out-File -FilePath $env:GITHUB_ENV -Append
"npm_config_msvs_version=2022" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Fix node-gyp and Python
run: python3 -m pip install packaging setuptools
- name: Setup MSVC (VS 2022 dev env)
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Install latest version of NPM
run: 'npm install -g npm@11.6.2'
- name: Install globally node-gyp, ts-node and nx packages
run: 'npm install --quiet -g node-gyp@10.2.0 ts-node@10.9.2 nx@^22.5.2'
- name: Configure npm python for node-gyp
shell: powershell
run: |
$py = (Get-Command python.exe).Source
Write-Host "python is: $py"
"npm_config_python=$py" | Out-File -FilePath $env:GITHUB_ENV -Append
"PYTHON=$py" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Configure Registry
shell: bash
run: |
if [ -n "${{ secrets.VERDACCIO_TOKEN }}" ]; then
echo "//packages.ever.co/:_authToken=${{ secrets.VERDACCIO_TOKEN }}" >> .npmrc
echo "registry=https://packages.ever.co/" >> .npmrc
echo "always-auth=true" >> .npmrc
echo 'registry "https://packages.ever.co/"' >> .yarnrc
sed -i.bak 's|https://registry.yarnpkg.com|https://packages.ever.co|g' yarn.lock
sed -i.bak 's|https://registry.npmjs.org|https://packages.ever.co|g' yarn.lock
rm -f yarn.lock.bak
fi
- name: Install Yarn dependencies
run: 'yarn install --network-timeout 1000000 --frozen-lockfile --ignore-scripts'
- name: Run Postinstall Manually
run: 'yarn postinstall.manual'
- name: Bump Agent version
uses: actions/github-script@v8
with:
script: |
const script = require('./.scripts/bump-version-electron.js')
console.log(script.agent(false))
env:
GAUZY_RELEASE_TAG: ${{ needs.check-release-tag.outputs.tag }}
PROJECT_REPO: 'https://github.com/ever-co/ever-gauzy.git'
AGENT_APP_NAME: 'gauzy-agent'
# Demo electron releases go to the same repo
AGENT_APP_REPO_NAME: 'ever-gauzy'
AGENT_APP_REPO_OWNER: 'ever-co'
COMPANY_SITE_LINK: 'https://gauzy.co'
AGENT_APP_DESCRIPTION: 'Gauzy Agent'
AGENT_APP_ID: 'com.ever.gauzyagent'
- name: Fix Node.js PATH for child processes
shell: powershell
run: |
$ErrorActionPreference = "Stop"
$nodeExe = (Get-Command node -ErrorAction Stop).Source
$nodePath = Split-Path $nodeExe -Parent
$npmGlobalBin = & npm config get prefix
$localBin = Join-Path $PWD "node_modules\.bin"
$yarnCmd = Get-Command yarn -ErrorAction SilentlyContinue
$yarnPath = if ($yarnCmd) { Split-Path $yarnCmd.Source -Parent } else { "" }
$npmNodeExe = Join-Path $npmGlobalBin "node.exe"
if (-not (Test-Path $npmNodeExe)) { Copy-Item $nodeExe $npmNodeExe -Force }
$localNodeExe = Join-Path $localBin "node.exe"
if (-not (Test-Path $localNodeExe)) { Copy-Item $nodeExe $localNodeExe -Force }
$newPath = "$nodePath;$npmGlobalBin;$localBin;$yarnPath;$($env:PATH)"
"PATH=$newPath" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
@($nodePath, $npmGlobalBin, $localBin, $yarnPath) | Where-Object { $_ } | ForEach-Object {
$_ | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
}
"NODE=$nodeExe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
"NODE_PATH=$nodePath" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
$env:PATH = $newPath
[System.Environment]::SetEnvironmentVariable("PATH", $newPath, "Process")
- name: Ensure dist directory exists
shell: bash
run: mkdir -p dist/packages
- name: Increase file handle limits
shell: powershell
run: |
# Increase Node.js UV threadpool for parallel I/O (default is 4)
"UV_THREADPOOL_SIZE=32" | Out-File -FilePath $env:GITHUB_ENV -Append
# Patch graceful-fs to retry EMFILE errors with backoff
node -e "try { var gfs = require('graceful-fs'); gfs.gracefulify(require('fs')); console.log('graceful-fs patched'); } catch(e) { console.log('graceful-fs not available, skipping'); }"
- name: Reset NX
shell: powershell
run: npx nx reset
- name: Build Agent
shell: cmd
run: 'yarn build:agent:windows:release:gh:x64'
env:
USE_HARD_LINKS: false
ELECTRON_BUILDER_CACHE: ${{ github.workspace }}\.cache\electron-builder
GH_TOKEN: ${{ secrets.GH_TOKEN }}
EP_GH_IGNORE_TIME: true
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_TRACES_SAMPLE_RATE: '${{ secrets.SENTRY_TRACES_SAMPLE_RATE }}'
SENTRY_PROFILE_SAMPLE_RATE: '${{ secrets.SENTRY_PROFILE_SAMPLE_RATE }}'
SENTRY_HTTP_TRACING_ENABLED: '${{ secrets.SENTRY_HTTP_TRACING_ENABLED }}'
SENTRY_POSTGRES_TRACKING_ENABLED: '${{ secrets.SENTRY_POSTGRES_TRACKING_ENABLED }}'
SENTRY_PROFILING_ENABLED: '${{ secrets.SENTRY_PROFILING_ENABLED }}'
NX_NO_CLOUD: true
NX_PLUGIN_NO_TIMEOUTS: true
NX_DAEMON: false
PROJECT_REPO: 'https://github.com/ever-co/ever-gauzy.git'
# Demo electron releases go to the same repo
AGENT_APP_REPO_OWNER: 'ever-co'
AGENT_APP_REPO_NAME: 'ever-gauzy'
AGENT_APP_NAME: 'gauzy-agent'
AGENT_APP_DESCRIPTION: 'Gauzy Agent'
AGENT_APP_ID: 'com.ever.gauzyagent'
COMPANY_SITE_LINK: 'https://gauzy.co'