This repository automates Portable Version builds for HagiCode Desktop by resolving upstream Desktop and service releases, downloading the published Desktop archives, injecting the fixed portable payload, repacking the archive, and publishing a deterministic GitHub Release.
Portable builds now also bundle a pinned Node.js runtime and a preinstalled OpenSpec CLI so the unpacked archive can run node, openspec, and opsx without depending on machine-wide installations.
The main workflow is .github/workflows/portable-version-build.yml.
It supports three non-interactive entrypoints:
schedulepolls upstream releases on a daily cadence.workflow_dispatchsupports targeted rebuilds with optional Desktop tag, service tag, platform, dry-run, and force-rebuild inputs.repository_dispatchaccepts future-compatibleclient_payloadfields (desktopTag,serviceTag,platforms,forceRebuild,dryRun).
workflow_dispatch accepts these inputs:
desktop_tag: optional Desktop GitHub Release tag override.service_tag: optional service release tag override fromHagiCode-org/releases.platforms: comma-separated platforms. Supported values arelinux-x64,win-x64,osx-x64,osx-arm64, orall.force_rebuild: keep packaging even if the derived Portable Version release already exists.dry_run: skip GitHub Release publication while still resolving, staging, and packaging.
Repository dispatch payloads must include both desktopTag and serviceTag so the automation stays non-interactive.
The workflow expects a token with enough access to read release metadata from upstream repositories and create releases in HagiCode-org/portable-version.
Recommended repository secret:
PORTABLE_VERSION_GITHUB_TOKEN: personal access token or GitHub App token withcontents:readon upstream repositories andcontents:writeonportable-version.
Workflow permissions are set to:
contents: writeactions: read
The automation currently assumes:
- automatic scheduled builds default to the full platform matrix:
linux-x64,win-x64,osx-x64, andosx-arm64. - Desktop release assets are consumed directly instead of rebuilding from source. Current archive patterns are
hagicode-desktop-<version>.zipfor Linux,Hagicode.Desktop.<version>-unpacked.zipfor Windows, and the published macOS zip archives for macOS targets. - service release assets follow the framework-dependent naming contract used by HagiCode releases, for example
hagicode-0.1.0-beta.33-linux-x64-nort.zip. - the selected service asset extracts to a structure that contains
manifest.json,config/,lib/PCode.Web.dll,lib/PCode.Web.runtimeconfig.json, andlib/PCode.Web.deps.json. - the downloaded Desktop archive already contains
resources/extra/portable-fixed/orContents/Resources/extra/portable-fixed/, and the workflow injects the runtime intocurrent/inside that directory. - the portable toolchain manifest is defined in
config/portable-toolchain.json, which pins the Node.js distribution per platform and the bundled OpenSpec CLI package version. - the repacked archive stages the portable toolchain under
portable-fixed/toolchain/, includingnode/,npm-global/,bin/openspec,bin/opsx,env/activate.*, andtoolchain-manifest.json. - repacking the downloaded Desktop archive must preserve the original release layout so the resulting Portable Version still boots as a normal Desktop build.
Run the helper tests from the repository root for portable-version:
npm test
npm run verify:dry-runThe dry-run test uses fixture assets and validates Desktop archive download/extraction, service asset extraction, payload injection, archive repacking, and publish-ready inventory generation without creating a GitHub Release.
The dry-run flow now also validates portable toolchain staging and verification:
scripts/stage-portable-toolchain.mjsdownloads the pinned Node runtime intoportable-fixed/toolchain/node, installs the pinned OpenSpec CLI intoportable-fixed/toolchain/npm-global, and emitsportable-fixed/toolchain/toolchain-manifest.json.scripts/verify-portable-toolchain.mjsprepends the portable PATH and checksnode --version,openspec --version, andopsx status --help.- each platform workspace emits
toolchain-validation-<platform>.json, and the workflow uploads that report together with the repacked archive inventory and checksums.
Inside the unpacked archive, portable command entrypoints live under:
resources/extra/portable-fixed/toolchain/bin/openspecandopsxon Linux/macOSresources/extra/portable-fixed/toolchain/bin/openspec.cmdandopsx.cmdon Windowsresources/extra/portable-fixed/toolchain/env/activate.*helper scripts for session-scoped PATH injection
Use these recovery paths when a workflow run fails or must be replayed:
- Re-run the workflow with
workflow_dispatchand setdry_run=trueto confirm the build plan and payload staging without publishing. - If the derived Portable Version release already exists but the prior upload was partial, re-run with
force_rebuild=trueso archive injection and publication update the existing release. - If upstream assets changed or were republished, supply explicit
desktop_tagandservice_taginputs so the run uses a known-good version pair. - Inspect the uploaded workflow artifacts:
build-planportable-package-<platform>release-metadata-<release-tag>toolchain-validation-<platform>.json
- Review the workflow summary for the exact validation failure, missing platform asset, or publication command error.
Each successful build publishes:
- one deterministic Portable Version tag in the
pv-release-<hash>namespace, so the tag stays Portable Version specific instead of exposing Desktop/Service versions directly - repacked Desktop artifacts copied to deterministic asset names such as
hagicode-portable-linux-x64.zip - the normalized build manifest
- merged artifact inventory metadata
- merged SHA-256 checksums
- one toolchain validation report per platform, proving the bundled
node,openspec, andopsxcommands executed successfully before publication