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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
uses: actions/checkout@v7

- name: Set up Helm
uses: azure/setup-helm@v4
uses: azure/setup-helm@v5
with:
version: "v3.14.0"

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/helm-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up Helm
uses: azure/setup-helm@v4
uses: azure/setup-helm@v5
with:
version: "v3.14.0"

Expand Down Expand Up @@ -64,7 +64,7 @@ jobs:
echo "digest=${digest}" >> "$GITHUB_OUTPUT"

- name: Install cosign
uses: sigstore/cosign-installer@v3
uses: sigstore/cosign-installer@v4

- name: Log in to GHCR (cosign)
run: |
Expand All @@ -79,7 +79,7 @@ jobs:
"ghcr.io/clouddrove/charts/syncerd@${{ steps.push.outputs.digest }}"

- name: Install ORAS
uses: oras-project/setup-oras@v1
uses: oras-project/setup-oras@v2

- name: Log in to GHCR (ORAS)
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-azure-devops-extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Validate secret
shell: bash
Expand Down Expand Up @@ -71,7 +71,7 @@ jobs:
echo "path=azure-devops-extension/$vsix" >> "$GITHUB_OUTPUT"

- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: syncerd-azure-pipelines-vsix
path: ${{ steps.vsix.outputs.path }}
Expand Down
23 changes: 13 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,23 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v5
uses: actions/setup-go@v7
with:
go-version: "1.26"
cache: true

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
uses: goreleaser/goreleaser-action@v7
with:
version: latest
# Pinned to the major rather than latest: the action warns that
# "latest" is ambiguous and silently locks to ~> v2 anyway, and a
# release should not be the place a new major first runs.
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -37,24 +40,24 @@ jobs:
needs: goreleaser
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4

- name: Login to GHCR
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
# Publish to the canonical image name (Marketplace action uses this).
images: ghcr.io/clouddrove/syncerd
Expand All @@ -70,7 +73,7 @@ jobs:
type=raw,value=latest

- name: Build and push
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
file: ./Dockerfile
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/syncerd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up Go
uses: actions/setup-go@v5
uses: actions/setup-go@v7
with:
go-version: '1.26'
cache: false
Expand All @@ -37,15 +37,15 @@ jobs:
# Keep only the login steps for the registries you actually use.

- name: Login to GHCR
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Configure AWS credentials (ECR)
continue-on-error: true
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v6
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Expand All @@ -57,7 +57,7 @@ jobs:

- name: Azure login (ACR)
continue-on-error: true
uses: azure/login@v1
uses: azure/login@v3
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

Expand All @@ -71,13 +71,13 @@ jobs:

- name: Authenticate to Google Cloud (GCR)
continue-on-error: true
uses: google-github-actions/auth@v2
uses: google-github-actions/auth@v3
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}

- name: Set up gcloud (GCR)
continue-on-error: true
uses: google-github-actions/setup-gcloud@v2
uses: google-github-actions/setup-gcloud@v3

- name: Configure Docker for GCR
continue-on-error: true
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- A failed state save on the fail-fast path was silent, so everything copied before the abort was copied again on the next run with no explanation
- `git-sync` could not authenticate to Azure DevOps over git in `pat` mode, fixed in v0.2.1 and described there

### Fixed
- A mirrored pull request with no labels failed to update, taking the whole pull request with it. Once the mirror owned labels, an empty set was sent as null rather than as an empty array, and GitHub rejects that with 422. Most pull requests carry no labels, so this affected most of them. Found by the live suite on its first real run

### Added
- A live provider test suite behind the `live` build tag, run with `make test-live`. It creates two throwaway repositories against a real GitHub account, mirrors a pull request between them, and checks what actually landed, then deletes them. Every other test in the repository checks SyncerD against fakes written alongside the code, which is how three defects that made pull request mirroring inoperable passed a green suite and a review

### Security
- Cleared two advisories in transitive Go modules, an infinite loop in `golang.org/x/text` and an out of bounds read in `klauspost/compress`. Neither was reachable from SyncerD's own code, but both had fixes and a later change could have started calling them
- Patched a high severity advisory in `brace-expansion`, which the Azure DevOps extension pinned to exactly the affected version through an `overrides` entry

## [0.2.1] - 2026-08-19
Expand Down
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build test clean install lint
.PHONY: build test test-live clean install lint

# Version info injected at build time
VERSION ?= $(shell git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo dev)
Expand All @@ -13,6 +13,17 @@ build:
test:
go test -v ./...

# Run the live provider tests. These talk to a real GitHub account, create
# two throwaway repositories, use them, and delete them again. They are the
# only tests that prove a real API call works: everything else is checked
# against fakes written by the same hand as the code.
#
# SYNCERD_LIVE_GITHUB_TOKEN=ghp_... token with repo scope
# SYNCERD_LIVE_GITHUB_OWNER=acme account or org to create under
# SYNCERD_LIVE_KEEP=1 optional, skip cleanup to inspect
test-live:
go test -tags live -v -timeout 15m ./internal/livetest/

# Clean build artifacts
clean:
rm -f syncerd
Expand Down
28 changes: 28 additions & 0 deletions docs/git-sync-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,34 @@ Only GitHub sources can list pull requests today. A mirror that enables

---

## Live provider tests

Every other test in this repository checks SyncerD against fakes written by
whoever wrote the code, and that has already proved insufficient: three
defects that made pull request mirroring inoperable survived a green suite,
a passing verification run, and a review of their own change, because the
fakes agreed with the mistake. A real API does not.

```bash
export SYNCERD_LIVE_GITHUB_TOKEN=ghp_... # repo scope
export SYNCERD_LIVE_GITHUB_OWNER=your-account
make test-live
```

It creates two throwaway private repositories named `syncerd-live-*`, seeds
one with a branch, opens a pull request, mirrors the branches and then the
pull request to the other, and checks what actually landed: that the
destination pull request exists and is findable by its head branch, that
the body carries the marker and no live mention, that a second run changes
nothing, that a comment mirrors exactly once, and that closing the source
closes the mirror. Then it deletes both repositories. Set
`SYNCERD_LIVE_KEEP=1` to leave them behind and look.

Run it before a release that touches provider code. It is the only check
that would have caught the defects above.

---

## Cleanup

```bash
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ require (
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/klauspost/compress v1.18.7 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
Expand All @@ -53,8 +53,8 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/sync v0.21.0 // indirect
golang.org/x/text v0.39.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw=
github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
Expand Down Expand Up @@ -125,14 +125,14 @@ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus=
golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
Loading