diff --git a/.github/workflows/build-flow.yml b/.github/workflows/build-flow.yml index b018bfa..1fe2ee8 100644 --- a/.github/workflows/build-flow.yml +++ b/.github/workflows/build-flow.yml @@ -21,10 +21,9 @@ jobs: uses: wgtechlabs/build-flow-action/.github/workflows/app.yml@f8263c388160a62f4a0e72ed888e56c8e9159469 # v1.0.0 secrets: inherit with: - ci-profile: node-bun + # The Bun lockfile selects the default node-bun profile/package manager. # JavaScript/TypeScript CodeQL analyzes source without a compiler build. codeql-build-mode: none - ci-runtime-version: '24.21.0' ci-matrix-versions: '["22","24","26"]' # setup-bun reads packageManager: bun@1.3.10 from package.json. ci-setup-command: test "$(bun --version)" = '1.3.10' @@ -35,18 +34,4 @@ jobs: ci-coverage-command: bun run coverage ci-build-command: bun run build && bun run smoke && bun audit enable-package: true - enable-release: true - package-registry: both - package-npm-auth-method: oidc - package-manager: bun - release-package-manager: bun - - # Only an eligible main push may publish packages and a GitHub Release. - publish-dev-artifacts: false - publish-pr-artifacts: false - publish-manual-artifacts: false - - # The pinned workflow gates publication on CI/security and requires both - # registries plus successful package-job completion before GitHub Release. - package-publish-enabled: true - release-create: true + # Inherit dev/PR/manual publishing, both registries, npm OIDC, and releases. diff --git a/AGENTS.md b/AGENTS.md index 57bc2cc..653008e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -66,29 +66,23 @@ Use GHLT for authorized Clean Labels template setup. Preserve existing labels; a ## Build, package, and release policy -Use `wgtechlabs/build-flow-action` reusable workflows rather than inventing a new release pipeline. Package and release flows must be enabled for this repository, with both npm and GitHub Packages selected: +Use `wgtechlabs/build-flow-action` reusable workflows rather than inventing a new release pipeline. Enable the package flow explicitly; inherit the pinned defaults for releases, both npm and GitHub Packages, OIDC, and development/PR/manual publication. Keep project-specific validation inputs in the caller: ```yaml with: - ci-profile: node-bun ci-matrix-versions: '["22","24","26"]' enable-package: true - enable-release: true - package-registry: both - package-npm-auth-method: oidc - package-manager: bun - release-package-manager: bun ``` -The caller is [.github/workflows/build-flow.yml](.github/workflows/build-flow.yml). It pins released Build Flow v1.0.0 at immutable commit `f8263c388160a62f4a0e72ed888e56c8e9159469`. The package primitive is the released v2.3.0. Do not claim OIDC is active from an action release or a validation run alone. Package publication and GitHub Release creation are enabled for eligible pushes to `main`; dev, PR, and manual artifact publication are disabled. Promoting a PR to `main` can publish a release, so require explicit merge/release authorization and follow [docs/RELEASING.md](docs/RELEASING.md). +The caller is [.github/workflows/build-flow.yml](.github/workflows/build-flow.yml). It pins released Build Flow v1.0.0 at immutable commit `f8263c388160a62f4a0e72ed888e56c8e9159469`. The package primitive is the released v2.3.0. Do not claim OIDC is active from an action release or a validation run alone. Omit `publish-dev-artifacts`, `publish-pr-artifacts`, `publish-manual-artifacts`, and `package-publish-enabled` to inherit their `true` defaults. Development and preview builds are the project standard; do not disable them without an explicit request. Eligible PRs targeting `dev` use `pr`, dev pushes and promotion PRs use `dev`, other PRs targeting `main` use `patch`, and manual runs use `wip`. Eligible `main` pushes publish regular packages and a GitHub Release. Updating a PR can publish a preview; merging into `dev` or `main` can publish packages too. Honor the authorized delivery scope and follow [docs/RELEASING.md](docs/RELEASING.md). Use explicit Bun install/lint/typecheck/test/coverage/build commands supported by the package. The inspected `node-bun` defaults contain npm fallbacks; a failed Bun check must not turn into a successful fallback. Keep required security checks and run the Node package smoke check under each configured Node matrix version as part of the build gate. Do not claim that a parallel CodeQL job gates release unless its dependencies enforce that. -Use one compatible package identity/version for both registries: `@wgtechlabs/mdd-engine`. Confirm license, registry access, package contents, and public visibility before publishing. The npm authentication is Trusted Publishing with OIDC, using npm CLI >=11.5.1 on the pinned Node 24.21.0 runtime. Retain `package-npm-auth-method: oidc` when upgrading the orchestrator. Configure npm to trust `wgtechlabs/mdd-engine` / `build-flow.yml`, allow direct `npm publish`, and preserve `id-token: write` through the reusable workflow chain. OIDC publishing must not require or fall back to `NPM_TOKEN`. GitHub Packages still uses the separate built-in `GITHUB_TOKEN` with `packages: write`, and GitHub Releases require `contents: write`. Never hardcode or log tokens; retain permissions required by enabled comments or security features. +Use one compatible package identity/version for both registries: `@wgtechlabs/mdd-engine`. Confirm license, registry access, package contents, and public visibility before publishing. The npm authentication is Trusted Publishing with OIDC, using npm CLI >=11.5.1 on the pinned Node 24.21.0 runtime. Verify the inherited `package-npm-auth-method: oidc` default when upgrading the orchestrator. Configure npm to trust `wgtechlabs/mdd-engine` / `build-flow.yml`, allow direct `npm publish`, and preserve `id-token: write` through the reusable workflow chain. OIDC publishing must not require or fall back to `NPM_TOKEN`. GitHub Packages still uses the separate built-in `GITHUB_TOKEN` with `packages: write`, and GitHub Releases require `contents: write`. Never hardcode or log tokens; retain permissions required by enabled comments or security features. The first npm publication needs a one-time bootstrap if the package is absent. Use the preserved validated `0.1.0` tarball tied to the existing `v0.1.0` tag at finalized commit `3975075b4dee44806012e71d80e858ddcf2b39a9`; follow the verification and maintainer-authentication procedure in [docs/RELEASING.md](docs/RELEASING.md). Never rewrite the tag, duplicate an existing registry version, or blindly rerun a partial publication. Future eligible releases use automatic OIDC after the trusted publisher and workflow adoption are verified. -Required sequencing: validate source → finalize release source/version → build package → confirm successful publication to BOTH registries → publish GitHub Release. Partial registry publication is incomplete and must not unlock release. Do not silently change existing primitive defaults; document consumer policy overrides such as non-main artifact publishing. +Required sequencing on `main`: validate source → finalize release source/version → build package → confirm successful publication to BOTH registries → publish GitHub Release. Preview builds validate and publish from the triggering commit without release finalization or a GitHub Release. Partial registry publication is incomplete and must not unlock release. Preserve default bot detection and GitHub's fork-PR permission restrictions; never use `pull_request_target` to run contributor code with publishing credentials. Do not silently change existing primitive defaults; document the reason for any necessary consumer override. ### Release gate contract diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc6f507..03a3f2d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,4 +15,4 @@ Use Clean Commit messages: ` : ` or ` Labels are managed through [GHLT](https://github.com/warengonzaga/github-labels-template). Routine template updates use `ghlt apply --repo wgtechlabs/mdd-engine`; a destructive `migrate` requires explicit authorization. The initial migration has already been completed. -Do not publish packages or create releases from ordinary feature work. Follow [the release prerequisites](docs/RELEASING.md); eligible pushes to `main` publish to npm and GitHub Packages before creating a GitHub Release. +Follow [the release prerequisites and build channels](docs/RELEASING.md): eligible PRs targeting `dev` publish `pr` previews; pushes to `dev` and `dev` → `main` PRs publish `dev` previews. Other PRs targeting `main` publish `patch` previews, and manual runs publish `wip` previews. Eligible pushes to `main` publish regular packages before creating a GitHub Release. Both npm and GitHub Packages are enabled through Build Flow defaults. Pushing to an open PR can publish a new preview; a feature-branch push without an eligible PR does not trigger this workflow. diff --git a/README.md b/README.md index 1f478c8..b57a062 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The headless Markdown documentation compiler behind mdd. Give it a local project Built with TypeScript and Bun. Runs on Node.js 22, 24, and 26 without Bun. The default is the latest Node LTS, currently pinned to **24.21.0**. -> Initial implementation. Publishing to npm and GitHub Packages is configured for eligible pushes to `main`. Verify the first release before using registry installation instructions. See [releasing](docs/RELEASING.md). +> Build Flow's default channels publish development, PR, and manual preview packages alongside regular releases to npm and GitHub Packages. See [build channels and releasing](docs/RELEASING.md). ## A documentation project @@ -38,7 +38,9 @@ All settings are optional. Custom paths are relative to `mdd/config.json` and mu ## Compile without a website -After installing a locally packed copy of `@wgtechlabs/mdd-engine` in your Node project: +Install the regular package with `bun add @wgtechlabs/mdd-engine`. After a successful preview publication, use `bun add @wgtechlabs/mdd-engine@dev` for development builds or `bun add @wgtechlabs/mdd-engine@pr` for PRs targeting `dev`. Preview tags track the most recently published package in their channel; install an exact version to test a particular PR. You can also install a locally packed copy. + +In your Node project: ```js import { compileProject } from '@wgtechlabs/mdd-engine'; diff --git a/docs/RELEASING.md b/docs/RELEASING.md index d8c6c7b..7dd351d 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -1,20 +1,39 @@ # Releasing mdd-engine -## Automatic publication on main +## Automatic publication channels -[Build Flow](../.github/workflows/build-flow.yml) enables package publication and GitHub Release creation for eligible pushes to `main`. It publishes `@wgtechlabs/mdd-engine` to both npm (`registry.npmjs.org`) and GitHub Packages (`npm.pkg.github.com`). This package does not publish a container image to GHCR. +[Build Flow](../.github/workflows/build-flow.yml) uses its default development, pull-request, and manual preview publication channels, plus regular package publication with a GitHub Release from `main`. It publishes `@wgtechlabs/mdd-engine` to both npm (`registry.npmjs.org`) and GitHub Packages (`npm.pkg.github.com`). This package does not publish a container image to GHCR. The workflow pins released [Build Flow v1.0.0](https://github.com/wgtechlabs/build-flow-action/releases/tag/v1.0.0) at immutable commit [`f8263c388160a62f4a0e72ed888e56c8e9159469`](https://github.com/wgtechlabs/build-flow-action/commit/f8263c388160a62f4a0e72ed888e56c8e9159469). It uses the released [Package Build Flow v2.3.0](https://github.com/wgtechlabs/package-build-flow-action/releases/tag/v2.3.0). Workflow validation does not prove npm trust configuration or publication. -PRs, pushes to `dev`, and manual runs validate changes without publishing artifacts. Promoting this configuration to `main` enables the release path. Use a regular merge commit for the `dev` → `main` promotion and obtain explicit merge/release authorization. +The caller enables the package flow and inherits the pinned defaults for publication, both registries, npm OIDC, and releases. It does not override `publish-dev-artifacts`, `publish-pr-artifacts`, `publish-manual-artifacts`, or `package-publish-enabled`; all default to `true`. + +| Eligible trigger | Package version | Install tag | GitHub Release | +|---|---|---|---| +| Push to `dev` | `-dev.` | `dev` | None | +| PR targeting `dev` | `-pr.` | `pr` | None | +| PR from `dev` to `main` | `-dev.` | `dev` | None | +| Other PR targeting `main` | `-patch.` | `patch` | None | +| Manual run (`workflow_dispatch`) | `-wip.` | `wip` | None | +| Push to `main` with a planned version bump | Planned regular version | `latest` | After both registries succeed | + +`` is the version in `package.json`; `` is the first seven characters of the workflow's commit SHA. PR runs build GitHub's test-merge commit, not just the source-branch head. For example, a PR targeting `dev` can publish `0.1.0-pr.abcdef1`. + +After a successful publication, install a channel with `bun add @wgtechlabs/mdd-engine@dev` or `bun add @wgtechlabs/mdd-engine@pr`. Install an exact version to test a particular PR: the `pr` tag is shared across PRs, and `dev` is shared by dev pushes and promotion PRs. Each tag follows the most recently published package in its channel. Preview publication does not move `latest`. The package action's default PR comment provides installation instructions after successful publication. + +Commit-type filtering is disabled by default, so setup or documentation changes can publish previews too. Default bot detection can suppress publication. Fork PRs cannot be assumed publishable: GitHub restricts write permissions and credentials on those runs. Keep those platform restrictions; do not use `pull_request_target` to run contributor code with publishing credentials. + +The caller listens to pushes and PRs for `dev`/`main`, plus manual dispatch. Feature-branch pushes without an eligible PR do not run it. The standalone primitive's unplanned-main `staging` flow is not used here: the orchestrator plans and finalizes regular versions before main publication. Do not add a `release: published` trigger to republish a version already handled by the orchestrator. + +Updating a PR can publish a preview immediately. Merging into `dev` can publish a development package. Use a regular merge commit for the `dev` → `main` promotion, which can publish a regular release. These operations must stay within the authorized delivery scope. ## Required sequence 1. CI runs the Bun checks and packed-package smoke check on Node 22, 24, and 26. Dependency auditing and Gitleaks must pass. 2. Enabled CodeQL analysis must succeed before source finalization or publication. -3. Build Flow finalizes the planned version, source commit, changelog, and tag once. -4. The package job checks out that exact finalized commit, builds the package, and publishes to both registries. -5. Both registry results must report success and the complete package job must succeed before Build Flow creates the GitHub Release. +3. On `main`, Build Flow finalizes the planned version, source commit, changelog, and tag once. Preview builds skip release finalization and use the triggering commit. +4. The package job checks out that source commit, builds the package with the appropriate version/dist-tag, and publishes to both registries. +5. For `main`, both registry results must report success and the complete package job must succeed before Build Flow creates the GitHub Release. Preview builds do not create a GitHub Release. The package primitive's `artifact-published` output means at least one registry published. Build Flow checks complete publication separately; the aggregate flag alone is insufficient. Failure of either registry, a later package step, or required security analysis must prevent the GitHub Release. Preserve these guarantees when upgrading the workflow pin. @@ -25,7 +44,7 @@ The package primitive's `artifact-published` output means at least one registry - The OIDC publishing job requires npm CLI 11.5.1 or newer and Node 22.14.0 or newer; use the pinned Node 24.21.0 runtime. These publishing-tool requirements do not change the package's consumer runtime range. - Explicit CI overrides propagate failures. The build check includes `bun audit` before publication; the primitive's own audit runs after publishing and is not a substitute for this gate. - CodeQL uses `codeql-build-mode: none` for JavaScript/TypeScript source analysis. -- The caller selects `package-npm-auth-method: oidc`. npm publishing requires no `NPM_TOKEN` and must not fall back to a long-lived publish token. +- The caller inherits `package-npm-auth-method: oidc`. npm publishing requires no `NPM_TOKEN` and must not fall back to a long-lived publish token. - GitHub Packages uses its separate built-in `GITHUB_TOKEN` with `packages: write`; GitHub Release creation requires `contents: write`. npm OIDC does not replace these GitHub permissions. Preserve the caller's other required permissions and allow the authorized release commit/tag on `main`. - Retain the MIT `LICENSE` in the package and the repository metadata linking it to `wgtechlabs/mdd-engine`. @@ -41,11 +60,11 @@ Once the package exists on npm, add a GitHub Actions trusted publisher in its np | Environment | Leave empty unless the publishing job declares one | | Allowed actions | Enable **npm publish** for direct automatic publication | -Trust the calling workflow in this repository, even though reusable Build Flow workflows perform the upload. Grant `id-token: write` through the caller and called workflows, use GitHub-hosted runners, and retain `package-npm-auth-method: oidc` when upgrading Build Flow. Keep both registries enabled. See [npm's trusted-publishing guide](https://docs.npmjs.com/trusted-publishers/) for the platform requirements and settings. +Trust the calling workflow in this repository, even though reusable Build Flow workflows perform the upload. Grant `id-token: write` through the caller and called workflows, use GitHub-hosted runners, and verify the inherited `package-npm-auth-method: oidc` default when upgrading Build Flow. Keep both registries enabled. See [npm's trusted-publishing guide](https://docs.npmjs.com/trusted-publishers/) for the platform requirements and settings. After setup, eligible future releases publish automatically without an npm publish token or a per-version promotion step. Saving the trusted publisher does not verify it; confirm a successful OIDC publication before considering migration complete. -Create the trusted-publisher configuration shortly before an authorized promotion to `main`: it must complete its first successful publish within **48 hours of creation**. That successful publish validates the configuration and removes its expiry. If it expires before publication, recreate it to start a new 48-hour window; ordinary edits do not reset the deadline. Changing the repository or project identity requires a new trust relationship and validation window. See [npm's validation-window announcement](https://github.blog/changelog/2026-10-02-unvalidated-npm-trusted-publishing-configurations-now-expire/). The deadline does not replace the bootstrap, merge-authorization, or release-verification requirements below. +The trusted publisher identifies the caller `build-flow.yml` for all eligible channels; verify each publishing path against the registries rather than assuming a configured channel has succeeded. Create the configuration shortly before an authorized publication: it must complete its first successful publish within **48 hours of creation**. That successful publish validates the configuration and removes its expiry. If it expires before publication, recreate it to start a new 48-hour window; ordinary edits do not reset the deadline. Changing the repository or project identity requires a new trust relationship and validation window. See [npm's validation-window announcement](https://github.blog/changelog/2026-10-02-unvalidated-npm-trusted-publishing-configurations-now-expire/). The deadline does not replace the bootstrap, merge-authorization, or release-verification requirements below. ## Bootstrap the first npm version @@ -57,7 +76,7 @@ Verify the npm result, configure the trusted publisher, and complete the missing ## Verify a release -After the main workflow completes, verify the actual version in both registries, package contents and integrity, GitHub package visibility, and the GitHub Release tag/commit. GitHub Packages may initially be private; confirm the intended public visibility. Successful validation or an accepted workflow run does not prove publication. +After a publishing workflow completes, verify the actual version and dist-tag in both registries, package contents and integrity, and GitHub package visibility. For a regular release from `main`, also verify the GitHub Release tag/commit. Preview builds must update their expected channel tag without moving `latest`. For PRs, also verify the published version matches the test-merge commit and the installation comment is accurate. GitHub Packages may initially be private; confirm the intended public visibility. Successful validation or an accepted workflow run does not prove publication. The packed package must contain runtime JavaScript, TypeScript declarations, README, and LICENSE, while excluding tests, credentials, caches, and development files. Before the first release or a compatibility change, verify current Node 22/24/26 and the lowest version claimed by `engines.node`. @@ -65,13 +84,13 @@ The packed package must contain runtime JavaScript, TypeScript declarations, REA Registry publication is not atomic. If one registry succeeds and the other fails, the GitHub Release must remain unpublished. Do not delete the published version or blindly rerun the whole workflow: the primitive attempts both registries again and does not treat an existing version as a successful retry. -1. Record the finalized tag/commit, exact package version, successful registry, and failed job logs. Correct the failed registry's access issue: npm trusted-publisher identity/OIDC permissions (recreate an expired configuration) or GitHub package permissions, as applicable. -2. Retrieve the published tarball from the successful registry and verify its identity, version, metadata, integrity, and contents against the finalized source. Preserve those package bytes for recovery. -3. With explicit publication authorization, publish that verified tarball only to the missing registry using authentication accepted by that registry. Do not rebuild a different artifact, change the released version, or rewrite the finalized tag. -4. Verify the same version and package contents in both registries and all required checks on the finalized source. Only then create the GitHub Release for the existing verified tag with explicit release authorization. +1. Record the source commit, finalized tag if applicable, exact package version/dist-tag, successful registry, and failed job logs. Correct the failed registry's access issue: npm trusted-publisher identity/OIDC permissions (recreate an expired configuration) or GitHub package permissions, as applicable. +2. Retrieve the published tarball from the successful registry and verify its identity, version, metadata, integrity, and contents against that source. Preserve those package bytes for recovery. +3. With explicit publication authorization, publish that verified tarball only to the missing registry using authentication accepted by that registry and the recorded dist-tag. For preview recovery, explicitly use the recorded `--tag dev`, `--tag pr`, `--tag patch`, or `--tag wip` so the upload cannot move `latest`. Do not rebuild a different artifact, change the released version, or rewrite the finalized tag. +4. Verify the same version, dist-tag, and package contents in both registries and all required checks on that source. For a regular release from `main`, only then create the GitHub Release for the existing verified tag with explicit release authorization. Preview package recovery does not create a GitHub Release. This is a manual recovery procedure, not automatic retry support. No live partial-publication recovery has been exercised for mdd-engine. ## Normal delivery -Work on a short-lived branch from `dev`, squash its PR into `dev`, and promote `dev` to `main` through a regular merge commit with a meaningful `🚀 release:` title. See [AGENTS.md](../AGENTS.md) and [CONTRIBUTING.md](../CONTRIBUTING.md). +Work on a short-lived branch from `dev`, use its eligible PR preview for testing, and squash the PR into `dev` for a development package build. Promote `dev` to `main` through a regular merge commit with a meaningful `🚀 release:` title for a regular release. See [AGENTS.md](../AGENTS.md) and [CONTRIBUTING.md](../CONTRIBUTING.md).