An open API service indexing awesome lists of open source software.

https://github.com/hagicode-org/portable-version

Automation pipeline for building portable HagiCode Desktop releases with bundled runtime dependencies and preinstalled tooling.
https://github.com/hagicode-org/portable-version

desktop-app hagicode nodejs packaging portable-build release-automation

Last synced: 14 days ago
JSON representation

Automation pipeline for building portable HagiCode Desktop releases with bundled runtime dependencies and preinstalled tooling.

Awesome Lists containing this project

README

          

# portable-version

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.

## Trigger modes

The main workflow is `.github/workflows/portable-version-build.yml`.

It supports three non-interactive entrypoints:

- `schedule` polls the Desktop and Server index manifests on a daily cadence.
- `workflow_dispatch` supports targeted rebuilds with optional Desktop selector, service selector, platform, dry-run, and force-rebuild inputs.
- `repository_dispatch` accepts `client_payload` fields (`desktopTag`, `serviceTag`, `platforms`, `forceRebuild`, `dryRun`) and still requires both selectors so the automation stays non-interactive.

## Workflow inputs

`workflow_dispatch` accepts these inputs:

- `desktop_tag`: optional Desktop version selector. `refs/tags/v0.1.34`, `v0.1.34`, and `0.1.34` are normalized to the same selector.
- `service_tag`: optional Server version selector. `refs/tags/v0.1.0-beta.35`, `v0.1.0-beta.35`, and `0.1.0-beta.35` are normalized to the same selector.
- `platforms`: comma-separated platforms. Supported values are `linux-x64`, `win-x64`, `osx-x64`, `osx-arm64`, or `all`.
- `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.

## Data sources and download model

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 `path` from 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.

## Required secrets and permissions

Recommended repository secrets:

- `PORTABLE_VERSION_GITHUB_TOKEN`: token with `contents:write` on `HagiCode-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 least `Read` and `List` permissions. Example shape: `https://.blob.core.windows.net/?`.
- `PORTABLE_VERSION_SERVICE_AZURE_SAS_URL`: Server Azure Blob container SAS URL with at least `Read` and `List` permissions. Example shape: `https://.blob.core.windows.net/?`.

Workflow permissions are set to:

- `contents: write`
- `actions: read`

## Build assumptions

The automation currently assumes:

- scheduled builds default to the full platform matrix: `linux-x64`, `win-x64`, `osx-x64`, and `osx-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`, and `lib/PCode.Web.deps.json`.
- the downloaded Desktop asset already contains `resources/extra/portable-fixed/` or `Contents/Resources/extra/portable-fixed/`, and the workflow injects the runtime into `current/` 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/`, including `node/`, `npm-global/`, `bin/openspec`, `bin/opsx`, `env/activate.*`, and `toolchain-manifest.json`.

## Local verification

Run the helper tests from the repository root for `portable-version`:

```bash
npm test
npm run verify:dry-run
```

The 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 `
- `scripts/stage-portable-payload.mjs --service-asset-source `

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.

## Migration notes

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 in `build-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.version`
- `upstream.*.manifestUrl`
- `upstream.*.assetsByPlatform[platform].path`
- `downloads.strategy === "azure-blob-sas"`

## Manual recovery steps

Use these recovery paths when a workflow run fails or must be replayed:

1. Re-run the workflow with `workflow_dispatch` and set `dry_run=true` to confirm index resolution, payload staging, and repacking without publishing.
2. If the derived Portable Version release already exists but the prior upload was partial, re-run with `force_rebuild=true`.
3. If a specific upstream pair must be replayed, supply explicit `desktop_tag` and `service_tag` selectors.
4. Inspect the uploaded workflow artifacts:
- `build-plan`
- `portable-package-`
- `release-metadata-`
5. Review the workflow summary for the exact selector mismatch, missing indexed asset, SAS download failure, or publication error.

## Derived release outputs

Each successful build publishes:

- one deterministic Portable Version tag in the `pv-release-` 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`, and `opsx` commands executed successfully before publication