Skip to content

Publish release, main, and develop channels on GitHub Pages #19

Description

@PierreRaybaut

Note

This is an implementation-ready proposal based on a deployment audit
performed on 2026-09-06. GitHub Pages settings must be rechecked during
rollout, but the target URLs and storage-isolation trade-off are decided.

Summary

Publish three coexisting DataLab-Web channels from the existing GitHub
Pages project site:

URL Source Update rule
https://datalab-platform.com/web/ Latest stable release Updated after a successful release workflow
https://datalab-platform.com/web/main/ main Latest commit whose push CI succeeded
https://datalab-platform.com/web/develop/ develop Latest commit whose push CI succeeded

A failing or pending branch head must not replace the last successful
preview. All channels must be assembled into one atomic Pages artifact,
so updating one channel never deletes the other two.

Motivation

  • Preserve the stable application at its current URL.
  • Expose qualified main and develop builds for integration testing,
    demonstrations, and review.
  • Publish only commits that passed the repository's full branch CI.
  • Make every deployment traceable to release tags, commit SHAs, workflow
    runs, and dependency snapshots.
  • Avoid another host, repository, deployment branch, DNS entry, or
    server-side component.

Current state

The following was verified during the deployment audit:

  • /web/ is the Pages project site of DataLab-Platform/web and inherits
    the organization custom domain. It is not managed by the documentation
    deployment in DataLab-Platform.github.io.
  • The latest successful deployment at audit time was v0.9.0
    (6e484928fb17168ef7cff1f492a617caf52c7efa).
  • .github/workflows/release.yml deploys one dist/ artifact after a
    successful v*.*.* release build.
  • .github/workflows/deploy.yml performs an ad-hoc manual build and also
    deploys one dist/ artifact.
  • A Pages deployment replaces the whole project site. Independent
    deployments for the three paths would overwrite one another.
  • .github/workflows/tests.yml validates pushes and pull requests for
    both main and develop.
  • vite.config.ts already uses base: "./", making application assets
    compatible with arbitrary subpaths.
  • The github-pages environment currently permits main and tags
    matching v*.*.*, but not develop.

Goals

  • Preserve the stable release at /web/ without rebuilding or modifying
    its application files.
  • Publish the latest CI-qualified main and develop revisions.
  • Keep source selection deterministic, monotonic, and protected from
    pull-request or fork inputs.
  • Support revisions both with and without sigima-dependency.json.
  • Support a configured Sigima developmentRef in a static Pages build.
  • Validate the final composed site rather than only the Vite dev server.
  • Retain complete deployment artifacts for atomic recovery.

Non-goals

  • Changing DNS, the organization domain, or the documentation deployment.
  • Creating a generated-content branch or another hosting repository.
  • Publishing arbitrary feature-branch or pull-request previews.
  • Isolating browser storage between channels in this iteration.
  • Adding a channel selector or badge to the application UI.
  • Changing release versioning or SDK compatibility.

Proposed architecture

1. One artifact and one publisher

Assemble this layout before calling actions/upload-pages-artifact once:

site/
├── index.html                   # unchanged stable release
├── assets/                      # unchanged stable assets
├── ...
├── main/
│   ├── index.html
│   └── assets/...
├── develop/
│   ├── index.html
│   └── assets/...
└── deployment-manifest.json

The stable files must remain byte-for-byte identical to the selected
release asset. Assembly must reject incomplete channels, unsafe archive
entries, unexpected layouts, and reserved-path collisions.

2. Select immutable, qualified sources

Add scripts/resolve-pages-sources.mjs, keeping pure selection logic
separate from GitHub API I/O.

For each branch:

  1. Read the current branch head.
  2. Query successful .github/workflows/tests.yml runs filtered to
    event=push and the exact branch.
  3. Reject PR/fork runs and runs from another repository or workflow.
  4. Select the newest tested SHA still reachable from the branch head.
  5. Prevent rollback relative to the currently published manifest.
  6. Freeze the SHA and workflow run ID before checkout.

Do not select by workflow completion time alone: an older commit may
finish after a newer one. Cover pagination, reruns, pending or failed
heads, rewritten history, and first-deployment bootstrap. If no eligible
SHA exists, fail before any Pages upload.

For stable, select the latest non-draft, non-prerelease GitHub Release
and its exact datalab-web-<version>.tgz asset. Verify the tag/version,
archive layout, and API digest when available. Do not rebuild the tag or
depend on short-lived CI artifacts.

3. Build frozen branch revisions

Build main and develop in isolated parallel jobs:

Node.js 20 -> npm ci -> npm run build

Use each revision's own lockfile and scripts. Older main revisions may
not contain sigima-dependency.json or build:release; newer tooling
must not be imposed on them.

Dependency handling:

  • No manifest: use the revision's existing published dependency path.
  • developmentRef: null: use publishedRequirement.
  • Active developmentRef: run
    scripts/sigima_dependency.py prepare-pyodide without --github-env,
    publish the resulting wheel below the channel, and inject a
    browser-resolvable VITE_SIGIMA_INSTALL_SPEC.

The current /@fs/<runner path> override is Vite-specific and invalid on
Pages. Derive a root-relative URL from actions/configure-pages, such as:

/web/develop/wheels/<sigima-sha>/<wheel>

Confirm that the URL is used by the main runtime and all worker runtimes.
Preview builds must use npm run build, because release mode deliberately
ignores development dependency overrides.

4. Record provenance

Add scripts/assemble-pages.mjs and generate a versioned
deployment-manifest.json containing:

  • stable tag, commit, release ID, asset ID, and digest;
  • main and develop SHAs and qualifying workflow run IDs/attempts;
  • application versions;
  • published Sigima requirements and optional snapshot SHAs/wheel paths;
  • checksums for all three channel payloads.

This is deployment metadata, not an application API. Do not modify the
stable bundle merely to display channel information.

5. Publish only after trusted workflows

Make .github/workflows/deploy.yml the sole Pages publisher. Keep
workflow_dispatch and add workflow_run: completed triggers for:

  • tests, after a successful repository push to main or develop;
  • Release tarballs, after a successful stable tag and publication of
    the expected application asset.

The deployment workflow must live on the default branch (develop), as
required by workflow_run. Do not rely only on release: published,
because releases created with GITHUB_TOKEN do not normally trigger
another workflow.

Apply workflow-level concurrency to the complete sequence:

resolve -> build -> assemble -> smoke test -> deploy

Use cancel-in-progress: false and resolve sources only after entering
the serialized sequence. Each run must resolve the latest eligible state
instead of blindly trusting the triggering SHA.

6. Separate privileges

  • Resolver/build/test jobs: contents: read and actions: read.
  • Deployment job only: pages: write and id-token: write.
  • Never execute PR or fork code in the privileged job.
  • Publish only validated artifacts produced by the same workflow and the
    trusted stable release asset.

Remove the direct deploy-pages job and Pages permissions from
.github/workflows/release.yml, while preserving release checks,
tarballs, and GitHub Release publication. Ensure this ownership change
reaches main before the next release tag.

7. Document shared browser storage

All paths share one browser origin and therefore share origin-scoped
localStorage, IndexedDB, OPFS data, plugin trust state, and encrypted
AI-provider secrets.

Documentation must recommend a separate browser profile when preview
isolation matters. A separate tab or URL path is not an isolation
boundary. Subdomain isolation may be considered separately later.

Implementation checklist

Selection and assembly

  • Add scripts/resolve-pages-sources.mjs.
  • Add scripts/assemble-pages.mjs.
  • Add Vitest coverage under tests/ts/deployment/.
  • Cover out-of-order runs, reruns, failure/pending states, PR/fork
    rejection, ancestry, monotonicity, pagination, invalid assets,
    bad digests, unsafe archives, and path collisions.
  • Ensure all resolution failures occur before Pages upload.

Branch builds and dependency snapshots

  • Build frozen main and develop SHAs independently.
  • Support revisions without a dependency manifest.
  • Publish exactly the wheel matching an active full Sigima SHA.
  • Ensure deployed specs contain no /@fs/ or runner-local paths.
  • Upload immutable artifacts keyed by channel and source SHA.

Static deployment validation

  • Add playwright.pages.config.ts.
  • Add tests/pages/deployment.spec.ts.
  • Serve the composed artifact below /web/ without SPA fallback.
  • Exercise all three paths, reloads, and query strings.
  • Detect missing application assets, worker chunks, and wheels.
  • Assert visible signal and image output.
  • Exercise worker mode and at least one macro or notebook worker.
  • Cross-check runtime versions against the provenance manifest.

Workflow and recovery

  • Make .github/workflows/deploy.yml the only Pages publisher.
  • Remove root-only deployment from release.yml.
  • Scope permissions per job and validate all workflow_run fields.
  • Retain each complete site artifact, manifest, and checksums for at
    least 30 days.
  • Provide a manual recovery path that only accepts a validated prior
    successful composed artifact, never an arbitrary ref.

Documentation and rollout

  • Document the three URLs and update semantics in README.md.
  • Document deployment, failure, recovery, permissions, provenance,
    and shared storage in doc/releasing.md.
  • Validate workflow YAML and run actionlint when available.
  • Land release-publisher ownership changes on develop and main.
  • Temporarily allow develop in the github-pages environment.
  • Perform and validate the first composed deployment.
  • Remove obsolete main and v*.*.* deployment policies so old
    root-only workflows cannot overwrite the composed site.
  • Confirm Pages remains configured to use GitHub Actions.

Testing strategy

  • Run focused resolver/assembler tests first:
    npx vitest run tests/ts/deployment/pages.test.ts.
  • Run the mandatory 🟢 Vitest (TS) task: formatting check, ESLint, and
    all Vitest tests.
  • Build the selected historical main and current develop revisions
    with their own lockfiles.
  • Run the dedicated Playwright suite against the composed static
    artifact, not npm run dev.
  • Fixture-test event filtering and permission boundaries.
  • After approved rollout, smoke-test all public URLs, workers, wheel
    requests, plots, and manifest provenance.

No Python runtime change is expected. If src/runtime/*.py changes, also
run tests/python. Run npm run i18n:check if visible strings are added.

Acceptance criteria

  • /web/ remains the latest stable release when previews advance.
  • /web/main/ and /web/develop/ expose the latest eligible commits.
  • Failed or pending heads leave the previous previews online.
  • Updating any channel preserves the other two.
  • Obsolete, replayed, PR, fork, or out-of-order events cannot publish
    unqualified code or roll a channel backward.
  • Snapshot wheels load in the main runtime and workers.
  • The final static artifact passes Playwright before upload.
  • The manifest identifies and checksums every channel.
  • A failed build or smoke test leaves the current site untouched.
  • A prior complete site can be restored atomically.
  • Documentation explains shared browser storage and recommends a
    separate profile for preview testing.

Rollout sequence

  1. Merge the resolver, assembler, tests, and non-publishing workflow into
    develop.
  2. Remove direct release deployment and carry that change to main.
  3. Add develop to the environment's permitted deployment branches.
  4. Run and validate the first composed deployment manually.
  5. Remove the old main and v*.*.* deployment policies.
  6. Observe one develop update, one main update, and the next real
    release; confirm that each preserves the other channels.

If a failure occurs before upload, the current deployment remains active.
If the composed deployment must be reverted, restore a retained complete
site artifact rather than deploying only an old stable tarball.

Key references

  • .github/workflows/release.yml
  • .github/workflows/deploy.yml
  • .github/workflows/tests.yml
  • vite.config.ts
  • scripts/pack-app.mjs
  • scripts/sigima_dependency.py
  • sigima-dependency.json
  • src/runtime/dependencyConfig.ts
  • src/runtime/runtime.ts
  • src/runtime/workerBase.ts
  • playwright.config.ts
  • doc/testing-strategy.md
  • GitHub Pages custom domains across repositories
  • GitHub Actions workflow_run

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions