This repository automates Portable Version builds for HagiCode Desktop by resolving upstream Desktop and Server packages from the official index manifests, downloading the indexed raw assets through Azure Blob SAS URLs, injecting the fixed portable payload, repacking the archive, and publishing a deterministic GitHub Release.
Portable builds 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 the Desktop and Server index manifests on a daily cadence.workflow_dispatchsupports targeted rebuilds with optional Desktop selector, service selector, platform, dry-run, and force-rebuild inputs.repository_dispatchacceptsclient_payloadfields (desktopTag,serviceTag,platforms,forceRebuild,dryRun) and still requires both selectors so the automation stays non-interactive.
workflow_dispatch accepts these inputs:
desktop_tag: optional Desktop version selector.refs/tags/v0.1.34,v0.1.34, and0.1.34are normalized to the same selector.service_tag: optional Server version selector.refs/tags/v0.1.0-beta.35,v0.1.0-beta.35, and0.1.0-beta.35are normalized to the same selector.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.
When no selector is provided, the build plan resolves the latest indexed Desktop version and the latest indexed Server version.
Portable Version now uses a single upstream discovery model:
- Desktop index:
https://index.hagicode.com/desktop/index.json - Server index:
https://index.hagicode.com/server/index.json
The resolve step reads those manifests, picks the selected version entries, and records the matched platform assets. Packaging then downloads the raw archives by combining:
- the asset
pathfrom the index manifest - the Desktop Azure Blob SAS container URL from
PORTABLE_VERSION_DESKTOP_AZURE_SAS_URL - the Server Azure Blob SAS container URL from
PORTABLE_VERSION_SERVICE_AZURE_SAS_URL
The build plan artifact stores index metadata and the redacted Desktop/Server SAS container info, but it does not persist the live SAS token.
Recommended repository secrets:
PORTABLE_VERSION_GITHUB_TOKEN: token withcontents:writeonHagiCode-org/portable-version. It is only used for the final GitHub Release publication and release existence checks.PORTABLE_VERSION_DESKTOP_AZURE_SAS_URL: Desktop Azure Blob container SAS URL with at leastReadandListpermissions. Example shape:https://<account>.blob.core.windows.net/<desktop-container>?<sas-token>.PORTABLE_VERSION_SERVICE_AZURE_SAS_URL: Server Azure Blob container SAS URL with at leastReadandListpermissions. Example shape:https://<account>.blob.core.windows.net/<service-container>?<sas-token>.
Workflow permissions are set to:
contents: writeactions: read
The automation currently assumes:
- scheduled builds default to the full platform matrix:
linux-x64,win-x64,osx-x64, andosx-arm64. - Desktop assets are selected from index
assets[]by platform-specific naming rules. Linux prefers zip fixtures when present and otherwise falls back to the indexed AppImage; Windows uses the published*-unpacked.zip; macOS uses the published zip archives. - Server assets follow the framework-dependent naming contract used by HagiCode releases, for example
hagicode-0.1.0-beta.35-linux-x64-nort.zip. - the selected Server 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 asset 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.
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 preparation, Server payload extraction, toolchain staging, and archive repacking without publishing a GitHub Release.
For manual local staging you can override the network download step with fixture files:
scripts/prepare-packaging-workspace.mjs --desktop-asset-source <file-or-url>scripts/stage-portable-payload.mjs --service-asset-source <file-or-url>
Those overrides are intended for tests and diagnostics only. Production packaging must use index asset.path + PORTABLE_VERSION_DESKTOP_AZURE_SAS_URL or asset.path + PORTABLE_VERSION_SERVICE_AZURE_SAS_URL, depending on the asset source.
This repository no longer supports the old GitHub Release-driven build-plan structure.
Removed assumptions:
- upstream Desktop and Server discovery from GitHub Release metadata
- old
releaseId, release asset API URLs, and compatibility field mappings inbuild-plan.json - fallback downloads through release asset URLs during packaging
If you have external tooling that consumes build-plan.json, migrate it to the new structure:
upstream.desktop.version/upstream.service.versionupstream.*.manifestUrlupstream.*.assetsByPlatform[platform].pathdownloads.strategy === "azure-blob-sas"
Use these recovery paths when a workflow run fails or must be replayed:
- Re-run the workflow with
workflow_dispatchand setdry_run=trueto confirm index resolution, payload staging, and repacking without publishing. - If the derived Portable Version release already exists but the prior upload was partial, re-run with
force_rebuild=true. - If a specific upstream pair must be replayed, supply explicit
desktop_tagandservice_tagselectors. - Inspect the uploaded workflow artifacts:
build-planportable-package-<platform>release-metadata-<release-tag>
- Review the workflow summary for the exact selector mismatch, missing indexed asset, SAS download failure, or publication error.
Each successful build publishes:
- one deterministic Portable Version tag in the
pv-release-<hash>namespace - 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