Skip to content
Closed
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
126 changes: 126 additions & 0 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
name: Sync upstream

on:
schedule:
- cron: '23 6 * * *'
workflow_dispatch:

# Pushes use an app installation token; the built-in token only handles the
# 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@v3
id: app-token
with:
client-id: ${{ secrets.FORK_SYNC_APP_CLIENT_ID }}
private-key: ${{ secrets.FORK_SYNC_APP_KEY }}

- uses: actions/checkout@v7
with:
ref: peerdb
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}

# 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)
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 "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"

- 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'
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
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@v7
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/

# 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.rel.outputs.target != ''
run: |
git push --force origin peerdb
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,
# 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 }}"
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 issues on recovery
if: success()
env:
GH_TOKEN: ${{ github.token }}
run: |
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
80 changes: 67 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,74 @@
# 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). 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.

This repository holds supplementary Go cryptography packages.
## Layout

## Report Issues / Send Patches
| Ref | Contents | How it changes |
|---|---|---|
| `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 fork's N commits | Cut by the sync workflow on upstream releases; by hand for releases in between |

This repository uses Gerrit for code changes. To learn how to submit changes to
this repository, see https://go.dev/doc/contribute.
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
[`master...peerdb`](https://github.com/PeerDB-io/crypto/compare/master...peerdb).

The git repository is https://go.googlesource.com/crypto.
## Staying current with upstream

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.
`.github/workflows/sync-upstream.yml` runs daily (and on manual dispatch):

Note that contributions to the cryptography package receive additional scrutiny
due to their sensitive nature. Patches may take longer than normal to receive
feedback.
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 target tag.

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`
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**: 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's commits on `peerdb` via PR until
they apply cleanly, then re-run the workflow.
- **Changing the patch**: PR against `peerdb`, then re-run the workflow
(manual dispatch) to cut the tag.
- Keep the delta minimal.

## Scope

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

Upstream's BSD-style license applies; see `LICENSE`.
6 changes: 4 additions & 2 deletions ssh/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down