Signing and trust
This documentation section was written by Claude.
openocean-build only builds source that one of the project's maintainers has vouched for. Each project lists its maintainers in projects/<project>/maintainers.yaml, with their public keys in projects/<project>/keys/:
maintainers:
- name: Toby Schneider
github: tsaubergine # for web-UI merges (continuous builds)
gpg: ["A422 D0D2 1761 C039 62BB 3546 3372 3E2F 080B 6743"]
# ssh: ["ssh-ed25519 AAAA…"] # SSH signing keys are accepted too
Maintainers are per project: a maintainer of one project is trusted on no other. Only the listed fingerprints are trusted, even if keys/ holds other keys. ci/verify-signature makes every check below, and .github/CODEOWNERS requires review for changes to maintainers.yaml and keys/.
Releases: signed tags
With release.require_signed_tag: true (and source: git), a release is built from the upstream tag for the changelog version, and the build fails unless that tag is signed by one of the project's maintainers:
git tag -s v0.1.0 -m "Release 0.1.0"
git push origin v0.1.0
The tag must be an annotated, signed tag. A signed commit under an unsigned tag isn't enough, since the tag can be moved.
Projects with source: uscan (e.g. moos-ivp) instead download the upstream release tarball that debian/watch finds, so nothing checks a maintainer's signature for them. New projects should use source: git with signed tags.
Dependency projects have no maintainers to sign them. Each one pins its source to a reviewed commit (release.commit) instead.
Continuous builds: signed or merged heads
A continuous build is made from the head of the project's default branch only if either:
- A maintainer signed the commit (GPG or SSH, e.g.
git commit -S, orcommit.gpgsign = true), or - A maintainer merged it in GitHub's web UI (with
continuous.accept_github_merges, the default). GitHub signs web-UI merges with its own web-flow key. The build checks that signature, that the committer isGitHub <noreply@github.com>, and asks the GitHub API which pull request the commit came from and who merged it: that must be a maintainer'sgithublogin. This covers merge, squash and rebase merges.
flowchart TD
head["Default-branch head"] --> signed{"Signed by a maintainer's<br/>GPG or SSH key?"}
signed -->|yes| build["Build"]
signed -->|no| web{"Signed by GitHub's web-flow key,<br/>committer GitHub?"}
web -->|no| skip["Skip (reason in the run summary)"]
web -->|yes| pr{"Pull request merged by<br/>a maintainer's github login?"}
pr -->|yes| build
pr -->|no| skip
A head that fails these checks is skipped, not failed: the reason is in the run's summary, and the next trusted head is built as usual.
Note
A maintainer who merges from the command line must sign the merge commit (git merge -S); pushing someone else's unsigned commits directly to the default branch means the head isn't built until a trusted commit lands on top of it.