Skip to content
oss-kit
Install

Publishing happens in CI, tied to a release tag, never from a developer machine

Rule
R-PUB-01
Forge scope
GitHub and GitLab
Fixed by
oss-publish

A local publish ships whatever is in the working tree, from a machine holding a long-lived registry token. A CI publish tied to a release tag ships a commit that is in the repository and that CI has tested.

Observable check

the publish command runs in a release workflow or pipeline that is either triggered by a tag push or creates the release tag in the same run, and appears in no local script intended for manual use. A release-automation workflow such as release-please, semantic-release, or changesets satisfies this by the second clause: it triggers on a merge to the default branch and then tags, releases, and publishes in one run, so the published commit is still one the repository holds and CI has tested. What fails is a publish with no release tag on either side of it, and a publish a person can run from a working tree.

Where this comes from

Last read against these sources on 2026-07-28.

beginner-checks states it in Scorecard's own voice: 'Building locally on your laptop may seem simpler at first, but using an automated build process to create your package on your CI/CD system provides you with security benefits that pay off in the long run.' The Packaging check in checks.md is the observable form. Scope limit stated by Scorecard itself: Packaging 'is currently limited to repositories hosted on GitHub, and does not support other source hosting repositories'. If this rule stays Forges: both, its GitLab half is unsourced. The tag clause is this project position rather than Scorecard's: Packaging checks that a workflow publishes, not what triggered it. It is here because a publish with no release tag on either side of it leaves nothing a consumer can resolve back to a commit. It reads a run that creates the release tag as satisfying it, which is what release-please, semantic-release, and changesets all do, because the alternative rejects the way most registries are published to today for a reason the rule does not hold. What would retire the clause is a registry that resolves a published version to its commit without one.

Read the whole standard