Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: release-please

# Maintains a standing "Release PR" that accumulates feat:/fix:/deps: commits
# since the last release into a version bump + changelog (release-please-config.json
# controls which commit types count and where they land in CHANGELOG.md). Every
# push to main updates that one PR in place rather than opening a new one.
#
# The auto-merge step below merges that PR itself the moment required CI passes
# (same pattern as dependabot-auto-merge.yml), so a qualifying change on main
# becomes a tagged release with no manual version bump or `git tag` needed. That
# merge is what actually cuts the release: release-please creates the git tag +
# GitHub Release, which triggers release.yml's tag-triggered image publish
# (pinned :X.Y.Z / :X.Y images).
#
# Want a manual gate instead (open the PR, but decide yourself when to ship)?
# Delete the "Auto-merge the release PR" step below — everything else still
# works, you just click Merge on the PR when you're ready.
on:
push:
branches: [main]

permissions:
contents: write
pull-requests: write

concurrency:
group: release-please
cancel-in-progress: false

jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
id: release

- name: Auto-merge the release PR once it's open
if: steps.release.outputs.prs_created == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_JSON: ${{ steps.release.outputs.pr }}
run: |
PR_NUMBER=$(echo "$PR_JSON" | jq -r '.number')
gh pr merge --auto --squash "$PR_NUMBER" \
|| echo "Auto-merge not enabled — turn on 'Allow auto-merge' in repo settings, or merge #$PR_NUMBER manually."
21 changes: 4 additions & 17 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,7 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max

# On a version tag, create a GitHub Release with auto-generated notes. These
# also feed DockPull's own "What's changed" changelog panel.
release:
name: Create GitHub Release
needs: publish
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Create release
uses: softprops/action-gh-release@v3
with:
generate_release_notes: true
# NOTE: the GitHub Release itself is created by release-please.yml (with a
# changelog grouped by feat/fix/deps), not here — it creates the git tag as a
# side effect of publishing the Release, which is what triggers this workflow's
# tag push above. See release-please-config.json / release-please.yml.
3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "1.0.2"
}
44 changes: 38 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,42 @@ docker build -f server/Dockerfile -t dockpull .
with route changes.
- `SECURITY.md` — threat model and operator hardening guidance.

## Images / releases
## Commit message convention

`:latest` is published from every push to `main` (multi-arch: `linux/amd64` +
`linux/arm64`). Cutting a version tag (`git tag v1.2.0 && git push origin v1.2.0`)
publishes pinned `:1.2.0` / `:1.2` images and creates a GitHub Release with
auto-generated notes. Bump `version` in `server/package.json` +
`client/package.json` (and their lockfiles) to match the tag.
PR titles / squash-merge commit subjects use a `type: description` prefix —
this drives the automated release below (which commits count as releasable,
which changelog section they land in, and whether it's a patch or minor bump):

| Prefix | Meaning | Bump |
|---|---|---|
| `feat:` | user-facing feature | minor |
| `fix:` | bug fix | patch |
| `perf:` | performance fix | patch |
| `deps:` | dependency bump | patch |
| `security:` | security fix | patch |
| `docs:`, `chore:`, `refactor:`, `test:`, `build:`, `ci:` | no user-facing change | none — no release |

A commit with no recognized prefix doesn't count as releasable either. If the
*only* changes since the last release are unprefixed or in the "no release"
row, no Release PR gets opened — that's intentional (e.g. a docs typo fix
shouldn't ping every user's DockPull with "update available").

## Images / releases — fully automated

Releases are **not** cut by hand. [`release-please`](https://github.com/googleapis/release-please)
(`.github/workflows/release-please.yml`) watches every push to `main` and
maintains one standing "Release PR" with the next version + a changelog
generated from `feat:`/`fix:`/`deps:`/etc. commits since the last release. That
PR is set to auto-merge the moment required CI passes — merging it is what
actually cuts the release: release-please creates the git tag + GitHub Release,
which triggers `release.yml`'s tag-triggered build of pinned `:X.Y.Z` / `:X.Y`
images (`:latest` already tracks every `main` push independently of this).

Nothing to run by hand: no `npm version`, no `git tag`, no manually editing
`server/package.json` / `client/package.json` (the release PR does that too,
via `release-please-config.json`'s `extra-files`).

Want a manual gate instead of full auto-merge (e.g. to batch a few fixes into
one release, or review the changelog before it ships)? Delete the "Auto-merge
the release PR" step in `release-please.yml` — the Release PR still opens and
updates itself automatically, it'll just wait for a manual click on Merge.
31 changes: 31 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"release-type": "simple",
"packages": {
".": {
"release-type": "simple",
"changelog-path": "CHANGELOG.md",
"extra-files": [
{ "type": "json", "path": "server/package.json", "jsonpath": "$.version" },
{ "type": "json", "path": "server/package-lock.json", "jsonpath": "$.version" },
{ "type": "json", "path": "server/package-lock.json", "jsonpath": "$.packages[''].version" },
{ "type": "json", "path": "client/package.json", "jsonpath": "$.version" },
{ "type": "json", "path": "client/package-lock.json", "jsonpath": "$.version" },
{ "type": "json", "path": "client/package-lock.json", "jsonpath": "$.packages[''].version" }
]
}
},
"changelog-sections": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "perf", "section": "Performance" },
{ "type": "deps", "section": "Dependencies" },
{ "type": "security", "section": "Security" },
{ "type": "docs", "section": "Documentation", "hidden": true },
{ "type": "chore", "section": "Miscellaneous", "hidden": true },
{ "type": "refactor", "section": "Miscellaneous", "hidden": true },
{ "type": "test", "section": "Tests", "hidden": true },
{ "type": "build", "section": "Build", "hidden": true },
{ "type": "ci", "section": "CI", "hidden": true }
]
}