This example adapts PatrickJS's GitHub-Native npm Preview Packages Gist into a single pipeline.mjs.
For normal PR preview package publishing, prefer the generated path in generated-package-previews: sync.github.packagePreviews: true. This example shows the lower-level task/job shape that the generated preview system replaces for the common case.
The Gist uses separate GitHub Actions workflow templates for:
- PR preview packages in GitHub Packages.
- Main branch snapshot packages in GitHub Packages.
- Stable npm releases mirrored to GitHub Packages.
This example keeps the same model but makes pipeline.mjs the source of truth for jobs, triggers, local verification, and generated command sync.
The repo dogfoods this model for real: the root pipeline.ts generates @async/pipeline PR previews with packagePreviews: true, and still publishes main snapshots plus stable mirrors to GitHub Packages through lifecycle tasks. This example stays print-only so it is safe to run anywhere.
package.json
pipeline.mjs
scripts/validate-package-metadata.mjs
scripts/print-publish-plan.mjs
src/index.jstasks = validate metadata, verify package, pack package, print publish plans
jobs = prPreview, mainSnapshot, stableRelease
triggers = pull_request, push to main, release
sync = generated GitHub workflow and package-manager commandsTriggers describe when jobs should run. Sync describes which generated files should be kept current.
From this example directory:
pnpm install
pnpm async-pipeline list
pnpm async-pipeline run prPreview
pnpm async-pipeline sync listThe publish tasks print the npm/GitHub Packages commands they would run. They do not publish anything.
pnpm async-pipeline sync generate
pnpm async-pipeline sync checkThat can generate:
.github/workflows/async-pipeline.yml
.locks/pipeline/github-workflow.lock.json
.locks/pipeline/tasks.lock.jsonThe generated workflow is still only a bootloader. GitHub starts from YAML; pipeline.mjs decides which matching job to run after the workflow starts.
Before replacing the print-only publish plan with real npm publish commands:
- Remove
"private": trueor set it appropriately for your package. - Use a real scoped lowercase package name.
- Configure npm Trusted Publishing for the generated or hand-authored release workflow.
- Configure package write permissions for GitHub Packages.
- Keep fork PR publishing disabled unless you have a separate trust model.
- Use a package matrix if your publishable package is not at the repo root.
The original Gist includes hardened workflow templates for production publishing. This example shows how the same workflow shape maps into @async/pipeline.