From ab2740aaa5a6fbd8c9e35c7128979fa9042b994a Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 00:56:32 -0600 Subject: [PATCH 01/16] ssh: increase channel receive window to 8 MiB Upstream hardcodes a 2 MiB channel window (64 * 32 KiB packets, following OpenSSH) with no configuration hook. PeerDB tunnels bulk CDC traffic over SSH; on high-bandwidth, high-latency links the 2 MiB window caps throughput well below link capacity. 8 MiB covers the bandwidth-delay product of the links we see in practice. This is the only behavioral change this fork carries. --- ssh/channel.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ssh/channel.go b/ssh/channel.go index ba3279e91d..aa98947062 100644 --- a/ssh/channel.go +++ b/ssh/channel.go @@ -20,8 +20,10 @@ const ( // sent in a single packet. As per RFC 4253, section 6.1, 32k is also // the minimum. channelMaxPacket = 1 << 15 - // We follow OpenSSH here. - channelWindowSize = 64 * channelMaxPacket + // Upstream uses 64 packets (2 MiB), following OpenSSH. The larger + // receive window avoids throttling bulk CDC traffic on high-bandwidth, + // high-latency SSH links. + channelWindowSize = 256 * channelMaxPacket ) // NewChannel represents an incoming request to a channel. It must either be From 3389049c786b010d41057cd5376d1c34201ac28a Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 01:05:13 -0600 Subject: [PATCH 02/16] fork: add README and upstream sync workflow Documents how the fork works and automates tracking upstream releases: a daily workflow cherry-picks the fork-local commits onto new upstream release tags, validates with PeerDB's Go version, pushes a matching fork tag, and opens/bumps a sync-failure issue when something needs a human. The peerdb branch itself is PR-managed and never rewritten by automation. --- .github/workflows/sync-upstream.yml | 102 ++++++++++++++++++++++++++++ README.md | 59 ++++++++++++---- 2 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/sync-upstream.yml diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml new file mode 100644 index 0000000000..cb043f353c --- /dev/null +++ b/.github/workflows/sync-upstream.yml @@ -0,0 +1,102 @@ +name: Sync upstream + +on: + schedule: + - cron: '23 6 * * *' + workflow_dispatch: + +permissions: + contents: write + issues: write + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + ref: peerdb + fetch-depth: 0 + + - name: Find upstream release tag + id: tags + run: | + git remote add upstream https://github.com/golang/crypto + latest=$(git ls-remote --tags upstream 'v*' | awk -F/ '{print $NF}' \ + | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1) + current=$(git ls-remote --tags origin 'v*' | awk -F/ '{print $NF}' \ + | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1) + # Fork fixup tags use the patch slot, so compare on major.minor. + base="v$(echo "$current" | cut -d. -f1-2 | tr -d v).0" + if [ "$(printf '%s\n%s\n' "$latest" "$base" | sort -V | tail -1)" = "$base" ]; then + echo "Up to date: fork $current, upstream $latest" + echo "new=" >> "$GITHUB_OUTPUT" + else + echo "New upstream tag: $latest (fork is on $current)" + echo "new=$latest" >> "$GITHUB_OUTPUT" + fi + + - name: Cherry-pick fork commits onto new tag + if: steps.tags.outputs.new != '' + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git fetch --no-tags upstream tag '${{ steps.tags.outputs.new }}' + base=$(git merge-base HEAD '${{ steps.tags.outputs.new }}') + echo "Fork-local commits since $base:" + git log --oneline "$base"..HEAD + git checkout --detach '${{ steps.tags.outputs.new }}' + git cherry-pick "$base"..peerdb + + - name: Determine PeerDB Go version + id: go + run: | + version=$(curl -fsSL https://raw.githubusercontent.com/PeerDB-io/peerdb/main/flow/go.mod | awk '/^go /{print $2}') + echo "PeerDB uses go $version" + echo "version=$version" >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@v6 + with: + go-version: ${{ steps.go.outputs.version }} + check-latest: true + cache: false + + # Only the root ssh package: ssh/test and ssh/agent replay recorded + # transcripts that hardcode upstream's 2 MiB window, so the patch + # invalidates them by design. The root package runs full in-memory + # handshakes against the patched code. + - name: Validate + run: | + go build ./... + go test ./ssh/ + + - name: Push tag + if: steps.tags.outputs.new != '' + run: | + git tag '${{ steps.tags.outputs.new }}' + git push origin 'refs/tags/${{ steps.tags.outputs.new }}' + + - name: Open or bump failure issue + if: failure() + env: + GH_TOKEN: ${{ github.token }} + run: | + run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + existing=$(gh issue list -R "${{ github.repository }}" --label sync-failure --state open --json number --jq '.[0].number // empty') + if [ -n "$existing" ]; then + gh issue comment "$existing" -R "${{ github.repository }}" --body "Still failing: $run_url" + else + gh label create sync-failure -R "${{ github.repository }}" --force --description 'Upstream sync is broken' + body="The upstream sync workflow failed: $run_url"$'\n\n'"Likely a cherry-pick conflict with a new upstream release, or an ssh test failure. See README's Maintenance section. This issue gets bumped daily until a run succeeds." + gh issue create -R "${{ github.repository }}" --title 'Upstream sync failing' --label sync-failure --body "$body" + fi + + - name: Close failure issue on recovery + if: success() + env: + GH_TOKEN: ${{ github.token }} + run: | + existing=$(gh issue list -R "${{ github.repository }}" --label sync-failure --state open --json number --jq '.[0].number // empty') + if [ -n "$existing" ]; then + gh issue close "$existing" -R "${{ github.repository }}" --comment 'Sync succeeded; closing.' + fi diff --git a/README.md b/README.md index f69c623ff8..da3fa0bfc4 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,53 @@ -# Go Cryptography +# PeerDB fork of golang.org/x/crypto -[![Go Reference](https://pkg.go.dev/badge/golang.org/x/crypto.svg)](https://pkg.go.dev/golang.org/x/crypto) +PeerDB's fork of [golang/crypto](https://github.com/golang/crypto), carrying +a single patch: the SSH channel receive window in the `ssh` package is raised +from 2 MiB to 8 MiB (`channelWindowSize` in `ssh/channel.go`), which upstream +doesn't make configurable. PeerDB moves bulk CDC traffic through SSH tunnels; +on high-bandwidth, high-latency links the 2 MiB window caps throughput. -This repository holds supplementary Go cryptography packages. +## How it works -## Report Issues / Send Patches +- `peerdb` (default branch) carries the fork-local commits: the patch, this + README, and the sync workflow. It changes only via pull request and is + never force-pushed. `master` mirrors upstream and is never patched. +- Releases are tags, cut by automation: fork tag `vX.Y.0` = upstream tag + `vX.Y.0` + the fork-local commits cherry-picked on top. Fork-only fixups + use the patch slot (`vX.Y.1`). Tags are immutable — the Go module proxy + pins tag→hash on first fetch; never move one. +- A daily workflow (`.github/workflows/sync-upstream.yml`) looks for new + upstream release tags, cherry-picks the fork-local commits onto them, runs + the `ssh` package tests with PeerDB's Go version, and pushes the matching + fork tag. On failure it opens (or bumps) a `sync-failure` issue here. +- [PeerDB](https://github.com/PeerDB-io/peerdb) consumes this fork via + `replace golang.org/x/crypto => github.com/PeerDB-io/crypto` in + `flow/go.mod`; Renovate there follows this repo's tags. -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://go.dev/doc/contribute. +## Diff vs upstream -The git repository is https://go.googlesource.com/crypto. +`git diff vX.Y.0 ` against the matching upstream tag — +expected to stay a handful of lines in `ssh/channel.go` plus this README and +the sync workflow. -The main issue tracker for the crypto repository is located at -https://go.dev/issues. Prefix your issue with "x/crypto:" in the -subject line, so it is easy to find. +## Maintenance -Note that contributions to the cryptography package receive additional scrutiny -due to their sensitive nature. Patches may take longer than normal to receive -feedback. +- **Sync failure**: check the open `sync-failure` issue and the failed run. + Usually a cherry-pick conflict with a new upstream release or a test + failure: adjust the fork-local commits on `peerdb` via PR until they apply + cleanly, then re-run the workflow (`workflow_dispatch`). +- **Changing the patch**: PR against `peerdb`. To release the change without + waiting for the next upstream tag, cut a patch-slot tag by hand: cherry-pick + the fork-local commits onto the current upstream base tag and push the tag + (if `peerdb` already sits on the current base, just tag `peerdb`). The + PeerDB repo picks it up via Renovate. +- Keep the delta minimal. + +## Not a general-purpose fork + +Don't depend on this module — use `golang.org/x/crypto`. Issues in this repo +are only for the fork's automation; report `ssh` package issues +[upstream](https://go.dev/issues). + +## License + +Same BSD-style license as upstream; see `LICENSE`. From 793ba3e4d82bf2df04c9e7e7d3329465b9acc026 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 20:18:25 -0600 Subject: [PATCH 03/16] fork: make README human-readable Ref/tag semantics as a table, sync flow as a numbered list, direct scope statement. --- README.md | 103 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index da3fa0bfc4..d231bf95b9 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,72 @@ # PeerDB fork of golang.org/x/crypto -PeerDB's fork of [golang/crypto](https://github.com/golang/crypto), carrying -a single patch: the SSH channel receive window in the `ssh` package is raised -from 2 MiB to 8 MiB (`channelWindowSize` in `ssh/channel.go`), which upstream -doesn't make configurable. PeerDB moves bulk CDC traffic through SSH tunnels; -on high-bandwidth, high-latency links the 2 MiB window caps throughput. - -## How it works - -- `peerdb` (default branch) carries the fork-local commits: the patch, this - README, and the sync workflow. It changes only via pull request and is - never force-pushed. `master` mirrors upstream and is never patched. -- Releases are tags, cut by automation: fork tag `vX.Y.0` = upstream tag - `vX.Y.0` + the fork-local commits cherry-picked on top. Fork-only fixups - use the patch slot (`vX.Y.1`). Tags are immutable — the Go module proxy - pins tag→hash on first fetch; never move one. -- A daily workflow (`.github/workflows/sync-upstream.yml`) looks for new - upstream release tags, cherry-picks the fork-local commits onto them, runs - the `ssh` package tests with PeerDB's Go version, and pushes the matching - fork tag. On failure it opens (or bumps) a `sync-failure` issue here. -- [PeerDB](https://github.com/PeerDB-io/peerdb) consumes this fork via - `replace golang.org/x/crypto => github.com/PeerDB-io/crypto` in - `flow/go.mod`; Renovate there follows this repo's tags. - -## Diff vs upstream - -`git diff vX.Y.0 ` against the matching upstream tag — -expected to stay a handful of lines in `ssh/channel.go` plus this README and -the sync workflow. +PeerDB's fork of [golang/crypto](https://github.com/golang/crypto). It +carries one patch: the SSH channel receive window in the `ssh` package is +raised from upstream's hardcoded 2 MiB to 8 MiB (`channelWindowSize` in +`ssh/channel.go`). PeerDB moves bulk CDC (change data capture) traffic +through SSH tunnels, and SSH throughput caps at window ÷ round-trip time, so +on high-bandwidth, high-latency links the 2 MiB window holds throughput +below link capacity. + +## Layout + +| Ref | Contents | How it changes | +|---|---|---| +| `peerdb` (default branch) | The fork-local commits: the patch, this README, the sync workflow | Pull requests only | +| `master` | Upstream mirror from fork time; unused by the pipeline | Static | +| `vX.Y.0` tags | Upstream tag `vX.Y.0` + the fork-local commits | Cut by the sync workflow | +| `vX.Y.1`, `vX.Y.2`, … tags | Fork-only fixups on the same upstream base | Cut by hand | + +Tags are immutable: the Go module proxy pins tag→hash on first fetch, so a +published tag must never move. Upstream only ever tags `vX.Y.0`, which +leaves the patch slot free for fork fixups. To see the full delta: +`git diff vX.Y.0 ` against the matching upstream tag. + +## Staying current with upstream + +`.github/workflows/sync-upstream.yml` runs daily (and on manual dispatch): + +1. Checks upstream for a release tag newer than the fork's newest tag. +2. Cherry-picks the fork-local commits from `peerdb` onto the new upstream + tag as a detached head; the `peerdb` branch itself is untouched. +3. Builds all packages and tests the root `ssh` package, using the Go + version from PeerDB's `flow/go.mod`. +4. Pushes the matching fork tag. + +On failure the workflow opens a `sync-failure` issue, comments on it on each +subsequent failing day, and the next green run closes it. + +Validation covers the root `ssh` package, which runs full in-memory +handshakes against the patched code. The `ssh/test` and `ssh/agent` +packages replay recorded transcripts that embed upstream's 2 MiB window, so +they fail against this patch and are excluded. + +## How PeerDB consumes it + +`flow/go.mod` in [PeerDB](https://github.com/PeerDB-io/peerdb) keeps +`require golang.org/x/crypto` and adds +`replace golang.org/x/crypto => github.com/PeerDB-io/crypto`. Renovate in +that repo follows this repo's tags and opens the bump PRs. ## Maintenance -- **Sync failure**: check the open `sync-failure` issue and the failed run. - Usually a cherry-pick conflict with a new upstream release or a test - failure: adjust the fork-local commits on `peerdb` via PR until they apply - cleanly, then re-run the workflow (`workflow_dispatch`). -- **Changing the patch**: PR against `peerdb`. To release the change without - waiting for the next upstream tag, cut a patch-slot tag by hand: cherry-pick - the fork-local commits onto the current upstream base tag and push the tag - (if `peerdb` already sits on the current base, just tag `peerdb`). The - PeerDB repo picks it up via Renovate. +- **Sync failure**: the open `sync-failure` issue links the failed run. + Typical causes: a cherry-pick conflict with a new upstream release, or an + `ssh` test failure. Adjust the fork-local commits on `peerdb` via PR until + they apply cleanly, then re-run the workflow. +- **Changing the patch**: PR against `peerdb`. To release without waiting + for the next upstream tag, cherry-pick the fork-local commits onto the + current upstream base tag and push the next patch-slot tag; when `peerdb` + already sits on the current base, tag `peerdb` directly. - Keep the delta minimal. -## Not a general-purpose fork +## Scope -Don't depend on this module — use `golang.org/x/crypto`. Issues in this repo -are only for the fork's automation; report `ssh` package issues -[upstream](https://go.dev/issues). +This fork exists for PeerDB. Other projects should depend on +`golang.org/x/crypto`, and `ssh` package issues belong +[upstream](https://go.dev/issues). Issues in this repo cover the fork's +automation only. ## License -Same BSD-style license as upstream; see `LICENSE`. +Upstream's BSD-style license applies; see `LICENSE`. From a0560b3a2cb3424f4bb5fdf1d11e5190266050ac Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 21:06:35 -0600 Subject: [PATCH 04/16] fork: push sync results from an app installation token The sync workflow now updates the peerdb branch on each upstream release (rebase + force-push) in addition to cutting the tag, so the default branch tracks the latest upstream base. --- .github/workflows/sync-upstream.yml | 33 +++++++++++++++++------------ README.md | 7 +++--- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index cb043f353c..33e2f0ee39 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -5,18 +5,27 @@ on: - cron: '23 6 * * *' workflow_dispatch: +# Pushes use an app installation token; the built-in token only handles the +# failure issue. permissions: - contents: write + contents: read issues: write jobs: sync: runs-on: ubuntu-latest steps: + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.FORK_SYNC_APP_ID }} + private-key: ${{ secrets.FORK_SYNC_APP_KEY }} + - uses: actions/checkout@v5 with: ref: peerdb fetch-depth: 0 + token: ${{ steps.app-token.outputs.token }} - name: Find upstream release tag id: tags @@ -32,21 +41,18 @@ jobs: echo "Up to date: fork $current, upstream $latest" echo "new=" >> "$GITHUB_OUTPUT" else - echo "New upstream tag: $latest (fork is on $current)" + echo "New upstream tag: $latest (fork is on $current, base $base)" echo "new=$latest" >> "$GITHUB_OUTPUT" + echo "base=$base" >> "$GITHUB_OUTPUT" fi - - name: Cherry-pick fork commits onto new tag + - name: Rebase fork commits onto new tag if: steps.tags.outputs.new != '' run: | - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git fetch --no-tags upstream tag '${{ steps.tags.outputs.new }}' - base=$(git merge-base HEAD '${{ steps.tags.outputs.new }}') - echo "Fork-local commits since $base:" - git log --oneline "$base"..HEAD - git checkout --detach '${{ steps.tags.outputs.new }}' - git cherry-pick "$base"..peerdb + git config user.name 'peerdb-fork-sync[bot]' + git config user.email 'peerdb-fork-sync[bot]@users.noreply.github.com' + git fetch --no-tags upstream tag '${{ steps.tags.outputs.base }}' tag '${{ steps.tags.outputs.new }}' + git rebase --onto '${{ steps.tags.outputs.new }}' '${{ steps.tags.outputs.base }}' peerdb - name: Determine PeerDB Go version id: go @@ -70,9 +76,10 @@ jobs: go build ./... go test ./ssh/ - - name: Push tag + - name: Push branch and tag if: steps.tags.outputs.new != '' run: | + git push --force origin peerdb git tag '${{ steps.tags.outputs.new }}' git push origin 'refs/tags/${{ steps.tags.outputs.new }}' @@ -87,7 +94,7 @@ jobs: gh issue comment "$existing" -R "${{ github.repository }}" --body "Still failing: $run_url" else gh label create sync-failure -R "${{ github.repository }}" --force --description 'Upstream sync is broken' - body="The upstream sync workflow failed: $run_url"$'\n\n'"Likely a cherry-pick conflict with a new upstream release, or an ssh test failure. See README's Maintenance section. This issue gets bumped daily until a run succeeds." + body="The upstream sync workflow failed: $run_url"$'\n\n'"Likely a rebase conflict with a new upstream release, or an ssh test failure. See README's Maintenance section. This issue gets bumped daily until a run succeeds." gh issue create -R "${{ github.repository }}" --title 'Upstream sync failing' --label sync-failure --body "$body" fi diff --git a/README.md b/README.md index d231bf95b9..a236143ea4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ below link capacity. | Ref | Contents | How it changes | |---|---|---| -| `peerdb` (default branch) | The fork-local commits: the patch, this README, the sync workflow | Pull requests only | +| `peerdb` (default branch) | Latest upstream release tag + the fork-local commits: the patch, this README, the sync workflow | Sync workflow rebases and force-pushes it on each upstream release; manual changes via pull request | | `master` | Upstream mirror from fork time; unused by the pipeline | Static | | `vX.Y.0` tags | Upstream tag `vX.Y.0` + the fork-local commits | Cut by the sync workflow | | `vX.Y.1`, `vX.Y.2`, … tags | Fork-only fixups on the same upstream base | Cut by hand | @@ -27,11 +27,10 @@ leaves the patch slot free for fork fixups. To see the full delta: `.github/workflows/sync-upstream.yml` runs daily (and on manual dispatch): 1. Checks upstream for a release tag newer than the fork's newest tag. -2. Cherry-picks the fork-local commits from `peerdb` onto the new upstream - tag as a detached head; the `peerdb` branch itself is untouched. +2. Rebases the fork-local commits onto the new upstream tag. 3. Builds all packages and tests the root `ssh` package, using the Go version from PeerDB's `flow/go.mod`. -4. Pushes the matching fork tag. +4. Force-pushes `peerdb` and pushes the matching fork tag. On failure the workflow opens a `sync-failure` issue, comments on it on each subsequent failing day, and the next green run closes it. From 1d8609916077cb3a994e4089c02a62a351db8e70 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 21:07:57 -0600 Subject: [PATCH 05/16] fork: read the app id from secrets --- .github/workflows/sync-upstream.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 33e2f0ee39..d9004ac808 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/create-github-app-token@v2 id: app-token with: - app-id: ${{ vars.FORK_SYNC_APP_ID }} + app-id: ${{ secrets.FORK_SYNC_APP_ID }} private-key: ${{ secrets.FORK_SYNC_APP_KEY }} - uses: actions/checkout@v5 From 0412e964950651302e5aa9456d5ad6a62659aa68 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 21:12:45 -0600 Subject: [PATCH 06/16] fork: keep master on the upstream base of the current release master...peerdb is then always the full fork delta. The sync workflow fast-forwards master alongside each release. --- .github/workflows/sync-upstream.yml | 5 ++++- README.md | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index d9004ac808..f8db4df4dd 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -76,12 +76,15 @@ jobs: go build ./... go test ./ssh/ - - name: Push branch and tag + # master mirrors the upstream base of the current release, so + # master...peerdb always shows the full fork delta. + - name: Push branch, tag, and upstream-base master if: steps.tags.outputs.new != '' run: | git push --force origin peerdb git tag '${{ steps.tags.outputs.new }}' git push origin 'refs/tags/${{ steps.tags.outputs.new }}' + git push origin "$(git rev-parse '${{ steps.tags.outputs.new }}^{commit}')":refs/heads/master - name: Open or bump failure issue if: failure() diff --git a/README.md b/README.md index a236143ea4..82a8002ccf 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,14 @@ below link capacity. | Ref | Contents | How it changes | |---|---|---| | `peerdb` (default branch) | Latest upstream release tag + the fork-local commits: the patch, this README, the sync workflow | Sync workflow rebases and force-pushes it on each upstream release; manual changes via pull request | -| `master` | Upstream mirror from fork time; unused by the pipeline | Static | +| `master` | The upstream base of the current release, unpatched | Fast-forwarded by the sync workflow | | `vX.Y.0` tags | Upstream tag `vX.Y.0` + the fork-local commits | Cut by the sync workflow | | `vX.Y.1`, `vX.Y.2`, … tags | Fork-only fixups on the same upstream base | Cut by hand | Tags are immutable: the Go module proxy pins tag→hash on first fetch, so a published tag must never move. Upstream only ever tags `vX.Y.0`, which -leaves the patch slot free for fork fixups. To see the full delta: -`git diff vX.Y.0 ` against the matching upstream tag. +leaves the patch slot free for fork fixups. The full fork delta is +[`master...peerdb`](https://github.com/PeerDB-io/crypto/compare/master...peerdb). ## Staying current with upstream From 88076b06900f4c1691599777c2e2fe1aa5152c05 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 21:19:25 -0600 Subject: [PATCH 07/16] fork: handle upstream tag names colliding with fork tags Fork tags reuse upstream tag names with different content, so fetching an upstream tag by name is rejected as a clobber once the fork has released. Fetch the new upstream tag into FETCH_HEAD, derive the rebase base via merge-base, and pass the upstream commit to the push step so master gets the unpatched base. --- .github/workflows/sync-upstream.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index f8db4df4dd..dc99777ef8 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -46,13 +46,21 @@ jobs: echo "base=$base" >> "$GITHUB_OUTPUT" fi + # Upstream tag names collide with the fork's own (patched) tags, so the + # upstream tag is fetched into FETCH_HEAD instead of a local tag ref, + # and the rebase base is the merge-base rather than a tag name. - name: Rebase fork commits onto new tag + id: rebase if: steps.tags.outputs.new != '' run: | git config user.name 'peerdb-fork-sync[bot]' git config user.email 'peerdb-fork-sync[bot]@users.noreply.github.com' - git fetch --no-tags upstream tag '${{ steps.tags.outputs.base }}' tag '${{ steps.tags.outputs.new }}' - git rebase --onto '${{ steps.tags.outputs.new }}' '${{ steps.tags.outputs.base }}' peerdb + git fetch --no-tags upstream 'refs/tags/${{ steps.tags.outputs.new }}' + new_commit=$(git rev-parse 'FETCH_HEAD^{commit}') + base_commit=$(git merge-base HEAD "$new_commit") + echo "Rebasing $(git rev-list --count "$base_commit"..HEAD) fork commits from $base_commit onto $new_commit" + git rebase --onto "$new_commit" "$base_commit" peerdb + echo "new_commit=$new_commit" >> "$GITHUB_OUTPUT" - name: Determine PeerDB Go version id: go @@ -82,9 +90,9 @@ jobs: if: steps.tags.outputs.new != '' run: | git push --force origin peerdb - git tag '${{ steps.tags.outputs.new }}' + git tag '${{ steps.tags.outputs.new }}' peerdb git push origin 'refs/tags/${{ steps.tags.outputs.new }}' - git push origin "$(git rev-parse '${{ steps.tags.outputs.new }}^{commit}')":refs/heads/master + git push origin '${{ steps.rebase.outputs.new_commit }}':refs/heads/master - name: Open or bump failure issue if: failure() From 2222bcbb0929523eebfe0a0d3f64a9ed8e04ed8e Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 21:20:35 -0600 Subject: [PATCH 08/16] fork: temporary push self-test workflow --- .github/workflows/push-self-test.yml | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/push-self-test.yml diff --git a/.github/workflows/push-self-test.yml b/.github/workflows/push-self-test.yml new file mode 100644 index 0000000000..365127bd44 --- /dev/null +++ b/.github/workflows/push-self-test.yml @@ -0,0 +1,36 @@ +name: Sync push self-test + +on: workflow_dispatch + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ secrets.FORK_SYNC_APP_ID }} + private-key: ${{ secrets.FORK_SYNC_APP_KEY }} + - uses: actions/checkout@v5 + with: + ref: peerdb + fetch-depth: 0 + token: ${{ steps.app-token.outputs.token }} + - name: Exercise the sync push paths + run: | + git config user.name 'peerdb-fork-sync[bot]' + git config user.email 'peerdb-fork-sync[bot]@users.noreply.github.com' + before=$(git rev-parse HEAD) + git commit --allow-empty -m 'sync push self-test; reverted by the same run' + git push origin peerdb + echo 'branch push: OK' + git reset --hard "$before" + git push --force origin peerdb + echo 'force-push: OK' + git tag sync-push-self-test + git push origin refs/tags/sync-push-self-test + git push origin :refs/tags/sync-push-self-test + echo 'tag push and delete: OK' From c028a741aff017601f0a45565371d0e9f353943c Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 21:21:34 -0600 Subject: [PATCH 09/16] fork: remove push self-test workflow --- .github/workflows/push-self-test.yml | 36 ---------------------------- 1 file changed, 36 deletions(-) delete mode 100644 .github/workflows/push-self-test.yml diff --git a/.github/workflows/push-self-test.yml b/.github/workflows/push-self-test.yml deleted file mode 100644 index 365127bd44..0000000000 --- a/.github/workflows/push-self-test.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Sync push self-test - -on: workflow_dispatch - -permissions: - contents: read - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/create-github-app-token@v2 - id: app-token - with: - app-id: ${{ secrets.FORK_SYNC_APP_ID }} - private-key: ${{ secrets.FORK_SYNC_APP_KEY }} - - uses: actions/checkout@v5 - with: - ref: peerdb - fetch-depth: 0 - token: ${{ steps.app-token.outputs.token }} - - name: Exercise the sync push paths - run: | - git config user.name 'peerdb-fork-sync[bot]' - git config user.email 'peerdb-fork-sync[bot]@users.noreply.github.com' - before=$(git rev-parse HEAD) - git commit --allow-empty -m 'sync push self-test; reverted by the same run' - git push origin peerdb - echo 'branch push: OK' - git reset --hard "$before" - git push --force origin peerdb - echo 'force-push: OK' - git tag sync-push-self-test - git push origin refs/tags/sync-push-self-test - git push origin :refs/tags/sync-push-self-test - echo 'tag push and delete: OK' From a6922dfcb32ffc1979eb456db48e31b16cf39751 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 21:48:15 -0600 Subject: [PATCH 10/16] fork: reset the cron inactivity timer each run Public-repo cron workflows are disabled after 60 days without repository activity, and this repo is only active when upstream releases. Re-enabling the (already enabled) workflow via the API resets the timer. Inline gh call with the built-in token; no third-party action. --- .github/workflows/sync-upstream.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index dc99777ef8..a50ec8f6b1 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -6,15 +6,24 @@ on: workflow_dispatch: # Pushes use an app installation token; the built-in token only handles the -# failure issue. +# failure issue and the inactivity-timer reset. permissions: contents: read issues: write + actions: write jobs: sync: runs-on: ubuntu-latest steps: + # GitHub disables cron workflows in public repos after 60 days without + # repository activity, and this repo is only active when upstream + # releases. Re-enabling an enabled workflow resets that timer. + - name: Reset the scheduled-workflow inactivity timer + env: + GH_TOKEN: ${{ github.token }} + run: gh api -X PUT 'repos/${{ github.repository }}/actions/workflows/sync-upstream.yml/enable' + - uses: actions/create-github-app-token@v2 id: app-token with: From 3e732c26befac4e974dfef5b67dfd655486365a2 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 23:10:32 -0600 Subject: [PATCH 11/16] fork: create-github-app-token v3 (node 24 runtime) --- .github/workflows/sync-upstream.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index a50ec8f6b1..0480f13c1f 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -24,7 +24,7 @@ jobs: GH_TOKEN: ${{ github.token }} run: gh api -X PUT 'repos/${{ github.repository }}/actions/workflows/sync-upstream.yml/enable' - - uses: actions/create-github-app-token@v2 + - uses: actions/create-github-app-token@v3 id: app-token with: app-id: ${{ secrets.FORK_SYNC_APP_ID }} From 9f2f04251aab0b6d2313611a1db1dba66740586b Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 23:24:26 -0600 Subject: [PATCH 12/16] fork: bump checkout and setup-go to latest majors --- .github/workflows/sync-upstream.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 0480f13c1f..1a5c435267 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -30,7 +30,7 @@ jobs: app-id: ${{ secrets.FORK_SYNC_APP_ID }} private-key: ${{ secrets.FORK_SYNC_APP_KEY }} - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 with: ref: peerdb fetch-depth: 0 @@ -78,7 +78,7 @@ jobs: echo "PeerDB uses go $version" echo "version=$version" >> "$GITHUB_OUTPUT" - - uses: actions/setup-go@v6 + - uses: actions/setup-go@v7 with: go-version: ${{ steps.go.outputs.version }} check-latest: true From 160181ca32ca6de2b4dc5e9509898cd42a53be25 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 23:34:17 -0600 Subject: [PATCH 13/16] fork: one failure issue per failing run Each failing run opens its own issue; a green run closes every open sync-failure issue. Alerting subscribes to issue open/close events, so each failure and each recovery notifies exactly once. --- .github/workflows/sync-upstream.yml | 26 ++++++++++++-------------- README.md | 8 ++++---- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 1a5c435267..b524f3199f 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -103,27 +103,25 @@ jobs: git push origin 'refs/tags/${{ steps.tags.outputs.new }}' git push origin '${{ steps.rebase.outputs.new_commit }}':refs/heads/master - - name: Open or bump failure issue + # Each failing run opens its own issue; a green run closes every open + # sync-failure issue. Alerting subscribes to issue open/close events, + # so each failure and each recovery notifies exactly once. + - name: Open failure issue if: failure() env: GH_TOKEN: ${{ github.token }} run: | run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - existing=$(gh issue list -R "${{ github.repository }}" --label sync-failure --state open --json number --jq '.[0].number // empty') - if [ -n "$existing" ]; then - gh issue comment "$existing" -R "${{ github.repository }}" --body "Still failing: $run_url" - else - gh label create sync-failure -R "${{ github.repository }}" --force --description 'Upstream sync is broken' - body="The upstream sync workflow failed: $run_url"$'\n\n'"Likely a rebase conflict with a new upstream release, or an ssh test failure. See README's Maintenance section. This issue gets bumped daily until a run succeeds." - gh issue create -R "${{ github.repository }}" --title 'Upstream sync failing' --label sync-failure --body "$body" - fi + gh label create sync-failure -R "${{ github.repository }}" --force --description 'Upstream sync is broken' + body="The upstream sync workflow failed: $run_url"$'\n\n'"Likely a rebase conflict with a new upstream release, or an ssh test failure. See README's Maintenance section. Each failing run opens a new issue; the next green run closes all open ones." + gh issue create -R "${{ github.repository }}" --title "Upstream sync failing ($(date -u +%Y-%m-%d))" --label sync-failure --body "$body" - - name: Close failure issue on recovery + - name: Close failure issues on recovery if: success() env: GH_TOKEN: ${{ github.token }} run: | - existing=$(gh issue list -R "${{ github.repository }}" --label sync-failure --state open --json number --jq '.[0].number // empty') - if [ -n "$existing" ]; then - gh issue close "$existing" -R "${{ github.repository }}" --comment 'Sync succeeded; closing.' - fi + gh issue list -R "${{ github.repository }}" --label sync-failure --state open --json number --jq '.[].number' \ + | while read -r n; do + gh issue close "$n" -R "${{ github.repository }}" --comment 'Sync succeeded; closing.' + done diff --git a/README.md b/README.md index 82a8002ccf..11c6a3e425 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ leaves the patch slot free for fork fixups. The full fork delta is version from PeerDB's `flow/go.mod`. 4. Force-pushes `peerdb` and pushes the matching fork tag. -On failure the workflow opens a `sync-failure` issue, comments on it on each -subsequent failing day, and the next green run closes it. +Each failing run opens a fresh `sync-failure` issue; the next green run +closes all open ones. Validation covers the root `ssh` package, which runs full in-memory handshakes against the patched code. The `ssh/test` and `ssh/agent` @@ -49,8 +49,8 @@ that repo follows this repo's tags and opens the bump PRs. ## Maintenance -- **Sync failure**: the open `sync-failure` issue links the failed run. - Typical causes: a cherry-pick conflict with a new upstream release, or an +- **Sync failure**: each open `sync-failure` issue links its failed run. + Typical causes: a rebase conflict with a new upstream release, or an `ssh` test failure. Adjust the fork-local commits on `peerdb` via PR until they apply cleanly, then re-run the workflow. - **Changing the patch**: PR against `peerdb`. To release without waiting From 0fc09988fc5bcb6a10fc9ad901377d57c70eacaa Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Tue, 1 Sep 2026 23:58:54 -0600 Subject: [PATCH 14/16] fork: tag patch version = fork-local commit count Upstream only tags vX.Y.0 and the fork always carries at least one commit, so every cut gets a fresh tag name and published tags are never recreated. Fixup releases between upstream tags get their number from the same rule. --- .github/workflows/sync-upstream.yml | 13 +++++++++---- README.md | 16 ++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index b524f3199f..c210b4865a 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -93,14 +93,19 @@ jobs: go build ./... go test ./ssh/ - # master mirrors the upstream base of the current release, so - # master...peerdb always shows the full fork delta. + # The fork tag's patch version is the number of fork-local commits + # (upstream only tags vX.Y.0), so every cut gets a fresh tag name and + # published tags are never recreated. master mirrors the upstream base + # of the current release, so master...peerdb always shows the full + # fork delta. - name: Push branch, tag, and upstream-base master if: steps.tags.outputs.new != '' run: | git push --force origin peerdb - git tag '${{ steps.tags.outputs.new }}' peerdb - git push origin 'refs/tags/${{ steps.tags.outputs.new }}' + n=$(git rev-list --count '${{ steps.rebase.outputs.new_commit }}'..peerdb) + tag="$(echo '${{ steps.tags.outputs.new }}' | sed 's/\.0$//').$n" + git tag "$tag" peerdb + git push origin "refs/tags/$tag" git push origin '${{ steps.rebase.outputs.new_commit }}':refs/heads/master # Each failing run opens its own issue; a green run closes every open diff --git a/README.md b/README.md index 11c6a3e425..ea3e184223 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,13 @@ below link capacity. |---|---|---| | `peerdb` (default branch) | Latest upstream release tag + the fork-local commits: the patch, this README, the sync workflow | Sync workflow rebases and force-pushes it on each upstream release; manual changes via pull request | | `master` | The upstream base of the current release, unpatched | Fast-forwarded by the sync workflow | -| `vX.Y.0` tags | Upstream tag `vX.Y.0` + the fork-local commits | Cut by the sync workflow | -| `vX.Y.1`, `vX.Y.2`, … tags | Fork-only fixups on the same upstream base | Cut by hand | +| `vX.Y.N` tags | Upstream tag `vX.Y.0` + the N fork-local commits | Cut by the sync workflow on upstream releases; by hand for releases in between | -Tags are immutable: the Go module proxy pins tag→hash on first fetch, so a -published tag must never move. Upstream only ever tags `vX.Y.0`, which -leaves the patch slot free for fork fixups. The full fork delta is +The patch version is the fork-local commit count. Upstream only ever tags +`vX.Y.0` and the fork always carries at least one commit, so every fork tag +gets a fresh name and a published tag is never moved or recreated — which is +what the Go module proxy requires: it pins tag→hash on the first fetch. +(`v0.55.0` predates this scheme.) The full fork delta is [`master...peerdb`](https://github.com/PeerDB-io/crypto/compare/master...peerdb). ## Staying current with upstream @@ -54,9 +55,8 @@ that repo follows this repo's tags and opens the bump PRs. `ssh` test failure. Adjust the fork-local commits on `peerdb` via PR until they apply cleanly, then re-run the workflow. - **Changing the patch**: PR against `peerdb`. To release without waiting - for the next upstream tag, cherry-pick the fork-local commits onto the - current upstream base tag and push the next patch-slot tag; when `peerdb` - already sits on the current base, tag `peerdb` directly. + for the next upstream tag, tag `peerdb` as `vX.Y.N` (current upstream + base, N = the new fork-local commit count) and push the tag. - Keep the delta minimal. ## Scope From bacff5f7252b8b6493c75ff450e135af6c533ea6 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Wed, 2 Sep 2026 00:08:51 -0600 Subject: [PATCH 15/16] fork: release whenever the target tag is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The target tag is the upstream base's major.minor plus the number of extra commits in the fork. Any run — cron or dispatch — releases when that tag doesn't exist yet, covering new upstream releases and freshly merged fork PRs with one code path. Hand-cut fixup tags retire; the bump rides the normal weekly gomod group PR in peerdb. --- .github/workflows/sync-upstream.yml | 64 +++++++++++++---------------- README.md | 25 ++++++----- 2 files changed, 43 insertions(+), 46 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index c210b4865a..45bae6fee8 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -36,40 +36,39 @@ jobs: fetch-depth: 0 token: ${{ steps.app-token.outputs.token }} - - name: Find upstream release tag - id: tags + # The target tag is the upstream base's major.minor plus the number + # of extra commits in the fork. A release is due whenever that tag + # doesn't exist yet — a new upstream release, freshly merged fork PRs, + # or both. The upstream tag goes to FETCH_HEAD, never a local tag ref + # (the fork's own tag names live in the same vX.Y.Z namespace). + - name: Determine release + id: rel run: | git remote add upstream https://github.com/golang/crypto latest=$(git ls-remote --tags upstream 'v*' | awk -F/ '{print $NF}' \ | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1) - current=$(git ls-remote --tags origin 'v*' | awk -F/ '{print $NF}' \ - | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1) - # Fork fixup tags use the patch slot, so compare on major.minor. - base="v$(echo "$current" | cut -d. -f1-2 | tr -d v).0" - if [ "$(printf '%s\n%s\n' "$latest" "$base" | sort -V | tail -1)" = "$base" ]; then - echo "Up to date: fork $current, upstream $latest" - echo "new=" >> "$GITHUB_OUTPUT" + git fetch --no-tags upstream "refs/tags/$latest" + new_commit=$(git rev-parse 'FETCH_HEAD^{commit}') + base_commit=$(git merge-base HEAD "$new_commit") + n=$(git rev-list --count "$base_commit..HEAD") + target="${latest%.*}.$n" + if git ls-remote --exit-code origin "refs/tags/$target" >/dev/null; then + echo "Up to date: $target already released" + echo "target=" >> "$GITHUB_OUTPUT" else - echo "New upstream tag: $latest (fork is on $current, base $base)" - echo "new=$latest" >> "$GITHUB_OUTPUT" - echo "base=$base" >> "$GITHUB_OUTPUT" + echo "Release due: $target (upstream $latest + $n fork commits)" + echo "target=$target" >> "$GITHUB_OUTPUT" fi + echo "new_commit=$new_commit" >> "$GITHUB_OUTPUT" + echo "base_commit=$base_commit" >> "$GITHUB_OUTPUT" - # Upstream tag names collide with the fork's own (patched) tags, so the - # upstream tag is fetched into FETCH_HEAD instead of a local tag ref, - # and the rebase base is the merge-base rather than a tag name. - - name: Rebase fork commits onto new tag - id: rebase - if: steps.tags.outputs.new != '' + - name: Rebase fork commits onto new upstream base + if: steps.rel.outputs.target != '' && steps.rel.outputs.base_commit != steps.rel.outputs.new_commit run: | git config user.name 'peerdb-fork-sync[bot]' git config user.email 'peerdb-fork-sync[bot]@users.noreply.github.com' - git fetch --no-tags upstream 'refs/tags/${{ steps.tags.outputs.new }}' - new_commit=$(git rev-parse 'FETCH_HEAD^{commit}') - base_commit=$(git merge-base HEAD "$new_commit") - echo "Rebasing $(git rev-list --count "$base_commit"..HEAD) fork commits from $base_commit onto $new_commit" - git rebase --onto "$new_commit" "$base_commit" peerdb - echo "new_commit=$new_commit" >> "$GITHUB_OUTPUT" + echo "Rebasing onto ${{ steps.rel.outputs.new_commit }}" + git rebase --onto '${{ steps.rel.outputs.new_commit }}' '${{ steps.rel.outputs.base_commit }}' peerdb - name: Determine PeerDB Go version id: go @@ -93,20 +92,15 @@ jobs: go build ./... go test ./ssh/ - # The fork tag's patch version is the number of fork-local commits - # (upstream only tags vX.Y.0), so every cut gets a fresh tag name and - # published tags are never recreated. master mirrors the upstream base - # of the current release, so master...peerdb always shows the full - # fork delta. + # master mirrors the upstream base of the current release, so + # master...peerdb always shows the full fork delta. - name: Push branch, tag, and upstream-base master - if: steps.tags.outputs.new != '' + if: steps.rel.outputs.target != '' run: | git push --force origin peerdb - n=$(git rev-list --count '${{ steps.rebase.outputs.new_commit }}'..peerdb) - tag="$(echo '${{ steps.tags.outputs.new }}' | sed 's/\.0$//').$n" - git tag "$tag" peerdb - git push origin "refs/tags/$tag" - git push origin '${{ steps.rebase.outputs.new_commit }}':refs/heads/master + git tag '${{ steps.rel.outputs.target }}' peerdb + git push origin 'refs/tags/${{ steps.rel.outputs.target }}' + git push origin '${{ steps.rel.outputs.new_commit }}':refs/heads/master # Each failing run opens its own issue; a green run closes every open # sync-failure issue. Alerting subscribes to issue open/close events, diff --git a/README.md b/README.md index ea3e184223..e25f3c8bd0 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,13 @@ below link capacity. | Ref | Contents | How it changes | |---|---|---| -| `peerdb` (default branch) | Latest upstream release tag + the fork-local commits: the patch, this README, the sync workflow | Sync workflow rebases and force-pushes it on each upstream release; manual changes via pull request | +| `peerdb` (default branch) | Latest upstream release tag + the fork's commits: the patch, this README, the sync workflow | Sync workflow rebases and force-pushes it on each upstream release; manual changes via pull request | | `master` | The upstream base of the current release, unpatched | Fast-forwarded by the sync workflow | -| `vX.Y.N` tags | Upstream tag `vX.Y.0` + the N fork-local commits | Cut by the sync workflow on upstream releases; by hand for releases in between | +| `vX.Y.N` tags | Upstream tag `vX.Y.0` + the fork's N commits | Cut by the sync workflow on upstream releases; by hand for releases in between | -The patch version is the fork-local commit count. Upstream only ever tags -`vX.Y.0` and the fork always carries at least one commit, so every fork tag +The patch version is the number of extra commits in the fork. Upstream only +ever tags `vX.Y.0` and the fork always has at least one extra commit, so +every fork tag gets a fresh name and a published tag is never moved or recreated — which is what the Go module proxy requires: it pins tag→hash on the first fetch. (`v0.55.0` predates this scheme.) The full fork delta is @@ -27,11 +28,14 @@ what the Go module proxy requires: it pins tag→hash on the first fetch. `.github/workflows/sync-upstream.yml` runs daily (and on manual dispatch): -1. Checks upstream for a release tag newer than the fork's newest tag. -2. Rebases the fork-local commits onto the new upstream tag. +1. Computes the target tag: the latest upstream release's `vX.Y` plus the + number of extra commits in the fork. A release is due whenever that tag + doesn't exist yet — a new upstream release, freshly merged fork PRs, or + both. +2. Rebases the fork's commits onto the upstream tag when the base moved. 3. Builds all packages and tests the root `ssh` package, using the Go version from PeerDB's `flow/go.mod`. -4. Force-pushes `peerdb` and pushes the matching fork tag. +4. Force-pushes `peerdb` and pushes the target tag. Each failing run opens a fresh `sync-failure` issue; the next green run closes all open ones. @@ -52,11 +56,10 @@ that repo follows this repo's tags and opens the bump PRs. - **Sync failure**: each open `sync-failure` issue links its failed run. Typical causes: a rebase conflict with a new upstream release, or an - `ssh` test failure. Adjust the fork-local commits on `peerdb` via PR until + `ssh` test failure. Adjust the fork's commits on `peerdb` via PR until they apply cleanly, then re-run the workflow. -- **Changing the patch**: PR against `peerdb`. To release without waiting - for the next upstream tag, tag `peerdb` as `vX.Y.N` (current upstream - base, N = the new fork-local commit count) and push the tag. +- **Changing the patch**: PR against `peerdb`, then re-run the workflow + (manual dispatch) to cut the tag. - Keep the delta minimal. ## Scope From 1f46416c52a1dc85b2fe1a3add94118def5689a3 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Wed, 2 Sep 2026 00:48:13 -0600 Subject: [PATCH 16/16] fork: authenticate the app by client ID create-github-app-token v3 deprecated the app-id input. --- .github/workflows/sync-upstream.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 45bae6fee8..49bf5da928 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/create-github-app-token@v3 id: app-token with: - app-id: ${{ secrets.FORK_SYNC_APP_ID }} + client-id: ${{ secrets.FORK_SYNC_APP_CLIENT_ID }} private-key: ${{ secrets.FORK_SYNC_APP_KEY }} - uses: actions/checkout@v7