{"id":47705249,"url":"https://github.com/hagicode-org/portable-version","last_synced_at":"2026-04-14T07:04:23.389Z","repository":{"id":346249205,"uuid":"1188569606","full_name":"HagiCode-org/portable-version","owner":"HagiCode-org","description":"Automation pipeline for building portable HagiCode Desktop releases with bundled runtime dependencies and preinstalled tooling.","archived":false,"fork":false,"pushed_at":"2026-04-08T05:26:17.000Z","size":96,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-08T07:25:21.487Z","etag":null,"topics":["desktop-app","hagicode","nodejs","packaging","portable-build","release-automation"],"latest_commit_sha":null,"homepage":"https://hagicode.com/desktop/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HagiCode-org.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-22T09:14:41.000Z","updated_at":"2026-03-29T08:19:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/HagiCode-org/portable-version","commit_stats":null,"previous_names":["hagicode-org/portable-version"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/HagiCode-org/portable-version","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HagiCode-org%2Fportable-version","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HagiCode-org%2Fportable-version/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HagiCode-org%2Fportable-version/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HagiCode-org%2Fportable-version/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HagiCode-org","download_url":"https://codeload.github.com/HagiCode-org/portable-version/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HagiCode-org%2Fportable-version/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31785682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T02:24:21.117Z","status":"ssl_error","status_checked_at":"2026-04-14T02:24:20.627Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["desktop-app","hagicode","nodejs","packaging","portable-build","release-automation"],"created_at":"2026-04-02T17:53:53.615Z","updated_at":"2026-04-14T07:04:23.383Z","avatar_url":"https://github.com/HagiCode-org.png","language":"JavaScript","readme":"# portable-version\n\nThis 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.\n\nPortable 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.\n\n## Trigger modes\n\nThe main workflow is `.github/workflows/portable-version-build.yml`.\n\nIt supports three non-interactive entrypoints:\n\n- `schedule` polls the Desktop and Server index manifests on a daily cadence.\n- `workflow_dispatch` supports targeted rebuilds with optional Desktop selector, service selector, platform, dry-run, and force-rebuild inputs.\n- `repository_dispatch` accepts `client_payload` fields (`desktopTag`, `serviceTag`, `platforms`, `forceRebuild`, `dryRun`) and still requires both selectors so the automation stays non-interactive.\n\n## Workflow inputs\n\n`workflow_dispatch` accepts these inputs:\n\n- `desktop_tag`: optional Desktop version selector. `refs/tags/v0.1.34`, `v0.1.34`, and `0.1.34` are normalized to the same selector.\n- `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.\n- `platforms`: comma-separated platforms. Supported values are `linux-x64`, `win-x64`, `osx-x64`, `osx-arm64`, or `all`.\n- `force_rebuild`: keep packaging even if the derived Portable Version release already exists.\n- `dry_run`: skip GitHub Release publication while still resolving, staging, and packaging.\n\nWhen no selector is provided, the build plan resolves the latest indexed Desktop version and the latest indexed Server version.\n\n## Data sources and download model\n\nPortable Version now uses a single upstream discovery model:\n\n- Desktop index: `https://index.hagicode.com/desktop/index.json`\n- Server index: `https://index.hagicode.com/server/index.json`\n\nThe resolve step reads those manifests, picks the selected version entries, and records the matched platform assets. Packaging then downloads the raw archives by combining:\n\n- the asset `path` from the index manifest\n- the Desktop Azure Blob SAS container URL from `PORTABLE_VERSION_DESKTOP_AZURE_SAS_URL`\n- the Server Azure Blob SAS container URL from `PORTABLE_VERSION_SERVICE_AZURE_SAS_URL`\n\nThe build plan artifact stores index metadata and the redacted Desktop/Server SAS container info, but it does not persist the live SAS token.\n\n## Required secrets and permissions\n\nRecommended repository secrets:\n\n- `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.\n- `PORTABLE_VERSION_DESKTOP_AZURE_SAS_URL`: Desktop Azure Blob container SAS URL with at least `Read` and `List` permissions. Example shape: `https://\u003caccount\u003e.blob.core.windows.net/\u003cdesktop-container\u003e?\u003csas-token\u003e`.\n- `PORTABLE_VERSION_SERVICE_AZURE_SAS_URL`: Server Azure Blob container SAS URL with at least `Read` and `List` permissions. Example shape: `https://\u003caccount\u003e.blob.core.windows.net/\u003cservice-container\u003e?\u003csas-token\u003e`.\n\nWorkflow permissions are set to:\n\n- `contents: write`\n- `actions: read`\n\n## Build assumptions\n\nThe automation currently assumes:\n\n- scheduled builds default to the full platform matrix: `linux-x64`, `win-x64`, `osx-x64`, and `osx-arm64`.\n- 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.\n- Server assets follow the framework-dependent naming contract used by HagiCode releases, for example `hagicode-0.1.0-beta.35-linux-x64-nort.zip`.\n- 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`.\n- 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.\n- 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.\n- 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`.\n\n## Local verification\n\nRun the helper tests from the repository root for `portable-version`:\n\n```bash\nnpm test\nnpm run verify:dry-run\n```\n\nThe dry-run test uses fixture assets and validates Desktop archive preparation, Server payload extraction, toolchain staging, and archive repacking without publishing a GitHub Release.\n\nFor manual local staging you can override the network download step with fixture files:\n\n- `scripts/prepare-packaging-workspace.mjs --desktop-asset-source \u003cfile-or-url\u003e`\n- `scripts/stage-portable-payload.mjs --service-asset-source \u003cfile-or-url\u003e`\n\nThose 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.\n\n## Migration notes\n\nThis repository no longer supports the old GitHub Release-driven build-plan structure.\n\nRemoved assumptions:\n\n- upstream Desktop and Server discovery from GitHub Release metadata\n- old `releaseId`, release asset API URLs, and compatibility field mappings in `build-plan.json`\n- fallback downloads through release asset URLs during packaging\n\nIf you have external tooling that consumes `build-plan.json`, migrate it to the new structure:\n\n- `upstream.desktop.version` / `upstream.service.version`\n- `upstream.*.manifestUrl`\n- `upstream.*.assetsByPlatform[platform].path`\n- `downloads.strategy === \"azure-blob-sas\"`\n\n## Manual recovery steps\n\nUse these recovery paths when a workflow run fails or must be replayed:\n\n1. Re-run the workflow with `workflow_dispatch` and set `dry_run=true` to confirm index resolution, payload staging, and repacking without publishing.\n2. If the derived Portable Version release already exists but the prior upload was partial, re-run with `force_rebuild=true`.\n3. If a specific upstream pair must be replayed, supply explicit `desktop_tag` and `service_tag` selectors.\n4. Inspect the uploaded workflow artifacts:\n   - `build-plan`\n   - `portable-package-\u003cplatform\u003e`\n   - `release-metadata-\u003crelease-tag\u003e`\n5. Review the workflow summary for the exact selector mismatch, missing indexed asset, SAS download failure, or publication error.\n\n## Derived release outputs\n\nEach successful build publishes:\n\n- one deterministic Portable Version tag in the `pv-release-\u003chash\u003e` namespace\n- repacked Desktop artifacts copied to deterministic asset names such as `hagicode-portable-linux-x64.zip`\n- the normalized build manifest\n- merged artifact inventory metadata\n- merged SHA-256 checksums\n- one toolchain validation report per platform, proving the bundled `node`, `openspec`, and `opsx` commands executed successfully before publication\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhagicode-org%2Fportable-version","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhagicode-org%2Fportable-version","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhagicode-org%2Fportable-version/lists"}