Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37f8b6bee9 | |||
| d3bf9767f7 | |||
| 8fb10cfa94 | |||
| ab710e48bd | |||
| b70a65d18b | |||
| 8659e181c1 | |||
| fc2c609f9c | |||
| 7c183f9b51 | |||
| 4ab3e731a1 | |||
| b47191d0e7 | |||
| cbbe0d523c | |||
| 5996880e1f | |||
| b7399d7b57 | |||
| c8816bc3c0 | |||
| 6030864125 | |||
| a0aeedb796 | |||
| 5f4de58149 | |||
| 1412d00696 | |||
| ed25954c6c |
@@ -8,7 +8,13 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
runson: [ubuntu-latest, macos-latest, windows-latest]
|
runson: [
|
||||||
|
ubuntu-latest,
|
||||||
|
ubuntu-20.04,
|
||||||
|
macos-latest,
|
||||||
|
windows-latest,
|
||||||
|
windows-2019
|
||||||
|
]
|
||||||
uses: ./.github/workflows/actions-sync-e2e-test-called.yml
|
uses: ./.github/workflows/actions-sync-e2e-test-called.yml
|
||||||
with:
|
with:
|
||||||
runson: ${{ matrix.runson }}
|
runson: ${{ matrix.runson }}
|
||||||
|
|||||||
@@ -3,14 +3,64 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
jobs:
|
jobs:
|
||||||
CI:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.21
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: docker-compose run --rm lint
|
uses: golangci/golangci-lint-action@v4
|
||||||
- name: Test
|
with:
|
||||||
run: docker-compose run --rm test
|
version: v1.54.2
|
||||||
- name: E2E
|
unit-test:
|
||||||
run: docker-compose run --rm test-build
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.21
|
||||||
|
- name: Unit Tests
|
||||||
|
run: ./script/test
|
||||||
|
e2e-test:
|
||||||
|
needs: unit-test
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
platform: [linux]
|
||||||
|
arch: [amd64, arm64]
|
||||||
|
exclude:
|
||||||
|
# Exclude Windows AMD64 because it's not supported
|
||||||
|
- platform: windows
|
||||||
|
arch: amd64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.21
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build Binary for ${{ matrix.platform }}-${{ matrix.arch }}
|
||||||
|
run: |
|
||||||
|
if [[ "${{ matrix.platform }}" == "linux" ]]; then
|
||||||
|
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
GOOS=${{ matrix.platform }} GOARCH=${{ matrix.arch }} go build -o bin/actions-sync-${{ matrix.platform }}-${{ matrix.arch }} main.go
|
||||||
|
|
||||||
|
- name: Run End-to-End Tests for ${{ matrix.platform }}-${{ matrix.arch }}
|
||||||
|
run: ./script/test-ci bin/actions-sync-${{ matrix.platform }}-${{ matrix.arch }}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
- name: Set CURRENT_TAG
|
- name: Set CURRENT_TAG
|
||||||
run: echo "GORELEASER_CURRENT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
run: echo "GORELEASER_CURRENT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@f09f1a7bee7ae6b5153daf4e8c63cc8ce8c7e7d5
|
uses: goreleaser/goreleaser-action@v5
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
args: release --clean
|
args: release --clean
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ linters:
|
|||||||
- unparam
|
- unparam
|
||||||
run:
|
run:
|
||||||
tests: true
|
tests: true
|
||||||
skip-files:
|
|
||||||
- ".*_test\\.go$"
|
|
||||||
modules-download-mode: vendor
|
modules-download-mode: vendor
|
||||||
issues:
|
issues:
|
||||||
exclude-rules:
|
exclude-rules:
|
||||||
|
|||||||
+22
-14
@@ -1,16 +1,24 @@
|
|||||||
project_name: gh
|
project_name: actions/actions-sync
|
||||||
|
|
||||||
builds:
|
builds:
|
||||||
- <<: &build_defaults
|
- id: build
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- darwin
|
||||||
|
- windows
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
binary: bin/actions-sync
|
binary: bin/actions-sync
|
||||||
id: macos
|
ignore:
|
||||||
goos: [darwin]
|
- goos: windows
|
||||||
goarch: [amd64, arm64]
|
goarch: arm64
|
||||||
- <<: *build_defaults
|
env:
|
||||||
id: linux
|
- CGO_ENABLED=0
|
||||||
goos: [linux]
|
release:
|
||||||
goarch: [amd64, arm64]
|
github:
|
||||||
- <<: *build_defaults
|
owner: actions
|
||||||
id: windows
|
name: actions-sync
|
||||||
goos: [windows]
|
# Create the release as a draft so it can be tested before being published
|
||||||
goarch: [amd64]
|
# To test, go to the Actions tab and run the "Actions Sync E2E Sanity Test" workflow
|
||||||
|
draft: true
|
||||||
|
|
||||||
|
|||||||
+23
-23
@@ -1,23 +1,23 @@
|
|||||||
version: "3.5"
|
# version: "3.5"
|
||||||
services:
|
# services:
|
||||||
lint:
|
# lint:
|
||||||
image: lint
|
# image: lint
|
||||||
build:
|
# build:
|
||||||
context: .
|
# context: .
|
||||||
dockerfile: Dockerfile.cibuild
|
# dockerfile: Dockerfile.cibuild
|
||||||
entrypoint:
|
# entrypoint:
|
||||||
- script/lint
|
# - script/lint
|
||||||
test:
|
# test:
|
||||||
image: test
|
# image: test
|
||||||
build:
|
# build:
|
||||||
context: .
|
# context: .
|
||||||
dockerfile: Dockerfile.cibuild
|
# dockerfile: Dockerfile.cibuild
|
||||||
entrypoint:
|
# entrypoint:
|
||||||
- script/test
|
# - script/test
|
||||||
test-build:
|
# test-build:
|
||||||
image: test-build
|
# image: test-build
|
||||||
build:
|
# build:
|
||||||
context: .
|
# context: .
|
||||||
dockerfile: Dockerfile.cibuild
|
# dockerfile: Dockerfile.cibuild
|
||||||
entrypoint:
|
# entrypoint:
|
||||||
- script/test-build
|
# - script/test-build
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ if($IsLinux) {
|
|||||||
} elseif ($IsWindows) {
|
} elseif ($IsWindows) {
|
||||||
$file_postfix = "windows_amd64"
|
$file_postfix = "windows_amd64"
|
||||||
} elseif ($IsMacOS) {
|
} elseif ($IsMacOS) {
|
||||||
$file_postfix = "darwin_amd64"
|
$file_postfix = "darwin_arm64"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Download release to test
|
# Download release to test
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
script/build
|
#script/build
|
||||||
|
|
||||||
OUTPUT=$(mktemp)
|
OUTPUT=$(mktemp)
|
||||||
RESULT=-1
|
RESULT=-1
|
||||||
|
|||||||
Executable
+426
@@ -0,0 +1,426 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
#script/build
|
||||||
|
|
||||||
|
# if the first argument is missing then print usage and exit
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: $1 <path to actions-sync binary>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ACTIONS_SYNC_BINARY=$1
|
||||||
|
|
||||||
|
OUTPUT=$(mktemp)
|
||||||
|
RESULT=-1
|
||||||
|
|
||||||
|
SRC_GIT_DAEMON_PORT=9419
|
||||||
|
SRC_GIT_DAEMON_OUTPUT=$(mktemp)
|
||||||
|
SRC_GIT_DAEMON_PID=-1
|
||||||
|
|
||||||
|
DEST_GIT_DAEMON_PORT=9420
|
||||||
|
DEST_GIT_DAEMON_OUTPUT=$(mktemp)
|
||||||
|
DEST_GIT_DAEMON_PID=-1
|
||||||
|
|
||||||
|
DEST_API_PORT=8081
|
||||||
|
DEST_API_OUTPUT=$(mktemp)
|
||||||
|
DEST_API_PID=-1
|
||||||
|
trap "after_suite" EXIT
|
||||||
|
trap "after_suite" SIGINT
|
||||||
|
|
||||||
|
function test_version() {
|
||||||
|
version "version shouldn't require any flags"
|
||||||
|
|
||||||
|
echo "all version tests passed"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_pull() {
|
||||||
|
# Pull new repo
|
||||||
|
setup_src "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_cache
|
||||||
|
pull --repo-name "org/repo" "pulling new repo"
|
||||||
|
assert_cache_sha "org/repo" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "pulling new repo org/repo"
|
||||||
|
|
||||||
|
echo "all pull tests passed successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_push() {
|
||||||
|
# Push with a new change to main
|
||||||
|
setup_cache "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push "pushing new commit to main"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org/repo:heads/main to new commit"
|
||||||
|
|
||||||
|
# Push a non-linear change
|
||||||
|
setup_cache "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_dest "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
|
||||||
|
push "pushing to an old commit to main"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "updating heads/main to an old commit"
|
||||||
|
|
||||||
|
# Push with no changes to main
|
||||||
|
setup_cache "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_dest "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
push "pushing no changes to main"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "leaving org/repo:heads/main at existing commit"
|
||||||
|
|
||||||
|
# Push multiple branches
|
||||||
|
setup_cache "org/repo:heads/change:e9009d51dd6da2c363d1d14779c53dd27fcb0c52" \
|
||||||
|
"org/repo:heads/nochange:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_dest "org/repo:heads/change:a5984bb887dd2fcdc2892cd906d6f004844d1142" \
|
||||||
|
"org/repo:heads/nochange:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push "pushing multiple branches"
|
||||||
|
assert_dest_sha "org/repo" "heads/change" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org/repo:heads/change to new commit"
|
||||||
|
assert_dest_sha "org/repo" "heads/nochange" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "leaving org/repo:heads/nochange at existing commit"
|
||||||
|
|
||||||
|
# Pushing multiple branches and tags
|
||||||
|
setup_cache "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52" \
|
||||||
|
"org/repo:tags/v1:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142" \
|
||||||
|
"org/repo:tags/v1:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push "pushing multiple branches and tags"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org/repo:heads/main to new commit"
|
||||||
|
assert_dest_sha "org/repo" "tags/v1" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org/repo:tags/v1 to new commit"
|
||||||
|
|
||||||
|
# Pushing multiple repositories
|
||||||
|
setup_cache "org1/repo1:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52" \
|
||||||
|
"org1/repo2:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52" \
|
||||||
|
"org1/repo2:tags/v1:e9009d51dd6da2c363d1d14779c53dd27fcb0c52" \
|
||||||
|
"org2/repo1:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org1/repo1:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142" \
|
||||||
|
"org1/repo2:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142" \
|
||||||
|
"org1/repo2:tags/v1:a5984bb887dd2fcdc2892cd906d6f004844d1142" \
|
||||||
|
"org2/repo1:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push "pushing multiple repositories"
|
||||||
|
assert_dest_sha "org1/repo1" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org1/repo1:heads/main to new commit"
|
||||||
|
assert_dest_sha "org1/repo2" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org1/repo2:heads/main to new commit"
|
||||||
|
assert_dest_sha "org1/repo2" "tags/v1" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org1/repo2:tags/v1 to new commit"
|
||||||
|
assert_dest_sha "org2/repo1" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org2/repo1:tags/v1 to new commit"
|
||||||
|
|
||||||
|
# Honor --repo-name flag, ignore other cache entries
|
||||||
|
setup_cache "org/repo1:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52" \
|
||||||
|
"org/repo2:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org/repo1:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142" \
|
||||||
|
"org/repo2:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push2args --repo-name "org/repo1" "pushing only one of the repos in the cache"
|
||||||
|
assert_dest_sha "org/repo1" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org/repo1 passed in repo flag"
|
||||||
|
assert_dest_sha "org/repo2" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "org/repo2 not updated despite cache"
|
||||||
|
|
||||||
|
# Push to pre-existing org
|
||||||
|
setup_cache "org-already-exists/new-repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org-already-exists/new-repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push "pushing to existing org"
|
||||||
|
assert_dest_sha "org-already-exists/new-repo" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org-already-exists/new-repo"
|
||||||
|
|
||||||
|
# Push to pre-existing repo
|
||||||
|
setup_cache "org-already-exists/repo-already-exists:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org-already-exists/repo-already-exists:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push "pushing to existing repo"
|
||||||
|
assert_dest_sha "org-already-exists/repo-already-exists" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org-already-exists/repo-already-exists"
|
||||||
|
|
||||||
|
# Push to repo in user's account
|
||||||
|
setup_cache "monalisa/new-repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "monalisa/new-repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
push "pushing to authenticated user's account"
|
||||||
|
assert_dest_sha "monalisa/new-repo" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating monalisa/new-repo"
|
||||||
|
|
||||||
|
# Push to GHAE with impersonation
|
||||||
|
setup_cache "org-already-exists/ghae-repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org-already-exists/ghae-repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
push_impersonation "ghae-admin" "pushing to GHAE repo"
|
||||||
|
|
||||||
|
# Push to GHES with impersonation
|
||||||
|
setup_cache "org-already-exists/ghes-repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org-already-exists/ghes-repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
push_impersonation "ghes-admin" "pushing to GHES repo"
|
||||||
|
|
||||||
|
echo "all push tests passed successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_sync() {
|
||||||
|
# Sync no change without cached
|
||||||
|
setup_src "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_cache
|
||||||
|
setup_dest "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
sync --repo-name "org/repo" "syncing a new commit in an uncached repo"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "syncing no changes without cache"
|
||||||
|
|
||||||
|
# Sync a new commit without cache
|
||||||
|
setup_src "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_cache
|
||||||
|
setup_dest "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
sync --repo-name "org/repo" "syncing a new commit in an uncached repo"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "syncing a new commit without cache"
|
||||||
|
|
||||||
|
# Sync no change with uncached
|
||||||
|
setup_src "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_cache "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_dest "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
sync --repo-name "org/repo" "syncing a new commit in an uncached repo"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "syncing no changes with cache"
|
||||||
|
|
||||||
|
# Sync a new commit with cache
|
||||||
|
setup_src "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_cache "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_dest "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
sync --repo-name "org/repo" "syncing a new commit in an uncached repo"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "syncing a new commit with cache"
|
||||||
|
|
||||||
|
# Sync a non-linear change without cache
|
||||||
|
setup_src "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_cache
|
||||||
|
setup_dest "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
|
||||||
|
sync --repo-name "org/repo" "syncing an old commit in an uncached repo"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "syncing heads/main to an old commit without cache"
|
||||||
|
|
||||||
|
# Sync a non-linear change with cache
|
||||||
|
setup_src "org/repo:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
setup_cache "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
|
||||||
|
sync --repo-name "org/repo" "syncing an old commit in an cached repo"
|
||||||
|
assert_dest_sha "org/repo" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "syncing heads/main to an old commit with cache"
|
||||||
|
|
||||||
|
# Sync to a different repo
|
||||||
|
setup_src "org/repo:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_cache
|
||||||
|
setup_dest "org2/repo2:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
sync --repo-name "org/repo:org2/repo2" "syncing org/repo aliased to org2/repo2"
|
||||||
|
assert_dest_sha "org2/repo2" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "syncing org/repo aliased to org2/repo2"
|
||||||
|
|
||||||
|
# Honor --repo-name flag, ignore other cache entries
|
||||||
|
setup_cache "org/repo1:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52" \
|
||||||
|
"org/repo2:heads/main:e9009d51dd6da2c363d1d14779c53dd27fcb0c52"
|
||||||
|
setup_dest "org/repo1:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142" \
|
||||||
|
"org/repo2:heads/main:a5984bb887dd2fcdc2892cd906d6f004844d1142"
|
||||||
|
|
||||||
|
sync --repo-name "org/repo1" "syncing only one of the repos in the cache"
|
||||||
|
assert_dest_sha "org/repo1" "heads/main" "e9009d51dd6da2c363d1d14779c53dd27fcb0c52" "updating org/repo1 passed in repo flag"
|
||||||
|
assert_dest_sha "org/repo2" "heads/main" "a5984bb887dd2fcdc2892cd906d6f004844d1142" "org/repo2 not updated despite cache"
|
||||||
|
|
||||||
|
echo "all sync tests passed successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
function before_suite() {
|
||||||
|
set -e
|
||||||
|
$(
|
||||||
|
rm -rf test/tmp
|
||||||
|
mkdir -p test/tmp/dest
|
||||||
|
mkdir -p test/tmp/src
|
||||||
|
) >/dev/null
|
||||||
|
|
||||||
|
git daemon \
|
||||||
|
--reuseaddr \
|
||||||
|
--verbose \
|
||||||
|
--export-all \
|
||||||
|
--enable=receive-pack \
|
||||||
|
--port="$SRC_GIT_DAEMON_PORT" \
|
||||||
|
--base-path=test/tmp/src &>$SRC_GIT_DAEMON_OUTPUT &
|
||||||
|
SRC_GIT_DAEMON_PID=$!
|
||||||
|
|
||||||
|
git daemon \
|
||||||
|
--reuseaddr \
|
||||||
|
--verbose \
|
||||||
|
--export-all \
|
||||||
|
--enable=receive-pack \
|
||||||
|
--port="$DEST_GIT_DAEMON_PORT" \
|
||||||
|
--base-path=test/tmp/dest &>$DEST_GIT_DAEMON_OUTPUT &
|
||||||
|
DEST_GIT_DAEMON_PID=$!
|
||||||
|
|
||||||
|
# wait for the git daemons to start before continuing
|
||||||
|
|
||||||
|
if ! check_git_daemon $SRC_GIT_DAEMON_PORT; then
|
||||||
|
echo "timeout waiting for src git daemon to start"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! check_git_daemon $DEST_GIT_DAEMON_PORT; then
|
||||||
|
echo "timeout waiting for dest git daemon to start"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
go run test/github.go \
|
||||||
|
-p "$DEST_API_PORT" \
|
||||||
|
-git-daemon-url "git://localhost:$DEST_GIT_DAEMON_PORT/" &>$DEST_API_OUTPUT &
|
||||||
|
DEST_API_PID=$!
|
||||||
|
|
||||||
|
script/build
|
||||||
|
|
||||||
|
until $(curl --output /dev/null --silent --head --fail "http://localhost:$DEST_API_PORT/ping"); do
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
|
||||||
|
set +e
|
||||||
|
}
|
||||||
|
|
||||||
|
function after_suite() {
|
||||||
|
kill "$SRC_GIT_DAEMON_PID" "$DEST_GIT_DAEMON_PID" "$DEST_API_PID"
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_src() {
|
||||||
|
rm -rf test/tmp/src
|
||||||
|
mkdir -p test/tmp/src
|
||||||
|
|
||||||
|
for r in "$@"; do
|
||||||
|
local nwo=$(echo $r | cut -d':' -f1)
|
||||||
|
local refname=$(echo $r | cut -d':' -f2)
|
||||||
|
local sha=$(echo $r | cut -d':' -f3)
|
||||||
|
|
||||||
|
local org=$(echo $nwo | cut -d'/' -f1)
|
||||||
|
mkdir -p test/tmp/src/$org && cp -R test/fixtures/repo.git test/tmp/src/$nwo
|
||||||
|
echo "$sha" >"test/tmp/src/$nwo/refs/$refname"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_cache() {
|
||||||
|
rm -rf test/tmp/cache
|
||||||
|
mkdir -p test/tmp/cache
|
||||||
|
|
||||||
|
for r in "$@"; do
|
||||||
|
local nwo=$(echo $r | cut -d':' -f1)
|
||||||
|
local refname=$(echo $r | cut -d':' -f2)
|
||||||
|
local sha=$(echo $r | cut -d':' -f3)
|
||||||
|
mkdir -p test/tmp/cache/$nwo && cp -R test/fixtures/repo.git test/tmp/cache/$nwo/.git
|
||||||
|
echo "$sha" >"test/tmp/cache/$nwo/.git/refs/$refname"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_dest() {
|
||||||
|
rm -rf test/tmp/dest
|
||||||
|
mkdir -p test/tmp/dest
|
||||||
|
|
||||||
|
for r in "$@"; do
|
||||||
|
local nwo=$(echo $r | cut -d':' -f1)
|
||||||
|
local refname=$(echo $r | cut -d':' -f2)
|
||||||
|
local sha=$(echo $r | cut -d':' -f3)
|
||||||
|
mkdir -p test/tmp/dest/$nwo && cp -R test/fixtures/repo.git test/tmp/dest/$nwo/.git
|
||||||
|
echo "$sha" >"test/tmp/dest/$nwo/.git/refs/$refname"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function version() {
|
||||||
|
$ACTIONS_SYNC_BINARY version \
|
||||||
|
&>$OUTPUT ||
|
||||||
|
fail $1
|
||||||
|
}
|
||||||
|
|
||||||
|
function pull() {
|
||||||
|
$ACTIONS_SYNC_BINARY pull \
|
||||||
|
--cache-dir "test/tmp/cache" \
|
||||||
|
--source-url "git://localhost:$SRC_GIT_DAEMON_PORT" \
|
||||||
|
"$1" "$2" \
|
||||||
|
&>$OUTPUT ||
|
||||||
|
fail $3
|
||||||
|
}
|
||||||
|
|
||||||
|
function push() {
|
||||||
|
$ACTIONS_SYNC_BINARY push \
|
||||||
|
--cache-dir "test/tmp/cache" \
|
||||||
|
--disable-push-git-auth \
|
||||||
|
--destination-token "token" \
|
||||||
|
--destination-url "http://localhost:$DEST_API_PORT" \
|
||||||
|
&>$OUTPUT ||
|
||||||
|
fail "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function push2args() {
|
||||||
|
$ACTIONS_SYNC_BINARY push \
|
||||||
|
--cache-dir "test/tmp/cache" \
|
||||||
|
--disable-push-git-auth \
|
||||||
|
--destination-token "token" \
|
||||||
|
--destination-url "http://localhost:$DEST_API_PORT" \
|
||||||
|
"$1" "$2" \
|
||||||
|
&>$OUTPUT ||
|
||||||
|
fail $3
|
||||||
|
}
|
||||||
|
|
||||||
|
function push_impersonation() {
|
||||||
|
$ACTIONS_SYNC_BINARY push \
|
||||||
|
--cache-dir "test/tmp/cache" \
|
||||||
|
--disable-push-git-auth \
|
||||||
|
--destination-token "token" \
|
||||||
|
--destination-url "http://localhost:$DEST_API_PORT" \
|
||||||
|
--actions-admin-user $1 \
|
||||||
|
&>$OUTPUT ||
|
||||||
|
fail "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
function sync() {
|
||||||
|
$ACTIONS_SYNC_BINARY sync \
|
||||||
|
--cache-dir "test/tmp/cache" \
|
||||||
|
--source-url "git://localhost:$SRC_GIT_DAEMON_PORT" \
|
||||||
|
--disable-push-git-auth \
|
||||||
|
--destination-token "token" \
|
||||||
|
--destination-url "http://localhost:$DEST_API_PORT" \
|
||||||
|
"$1" "$2" \
|
||||||
|
&>$OUTPUT ||
|
||||||
|
fail $3
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert_cache_sha() {
|
||||||
|
nwo=$1
|
||||||
|
ref=$2
|
||||||
|
expected=$3
|
||||||
|
actual=$(cat "test/tmp/cache/$nwo/.git/refs/$ref")
|
||||||
|
[ "$actual" == "$expected" ] || fail "unexpected cache sha \`$expected != $actual\` - \`$nwo\` \`$ref\` - \`$4\`"
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert_dest_sha() {
|
||||||
|
nwo=$1
|
||||||
|
ref=$2
|
||||||
|
expected=$3
|
||||||
|
actual=$(cat "test/tmp/dest/$nwo/.git/refs/$ref")
|
||||||
|
[ "$actual" == "$expected" ] || fail "unexpected dest sha \`$expected != $actual\` - \`$nwo\` \`$ref\` - \`$4\`"
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail() {
|
||||||
|
MSG=$1
|
||||||
|
echo "FAIL: Failed $MSG"
|
||||||
|
echo -----output-----
|
||||||
|
cat $OUTPUT
|
||||||
|
echo -----/output-----
|
||||||
|
|
||||||
|
echo -----github git daemon output-----
|
||||||
|
cat $SRC_GIT_DAEMON_OUTPUT
|
||||||
|
echo -----/github git daemon output-----
|
||||||
|
|
||||||
|
echo -----ghes git daemon output-----
|
||||||
|
cat $DEST_GIT_DAEMON_OUTPUT
|
||||||
|
echo -----/ghes git daemon output-----
|
||||||
|
|
||||||
|
echo -----ghes api output-----
|
||||||
|
cat $DEST_API_OUTPUT
|
||||||
|
echo -----/ghes api output-----
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_git_daemon {
|
||||||
|
port=$1
|
||||||
|
for i in {1..10}; do
|
||||||
|
process=$(ps aux | grep "git daemon" | grep $port)
|
||||||
|
if [ -z "$process" ]; then
|
||||||
|
echo "Waiting for git daemon to start on port $port..."
|
||||||
|
sleep 1
|
||||||
|
else
|
||||||
|
echo "Git daemon is running on port $port"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "Git daemon did not start within the expected time."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
test_version
|
||||||
|
before_suite
|
||||||
|
test_pull
|
||||||
|
test_push
|
||||||
|
test_sync
|
||||||
+19
-16
@@ -71,11 +71,11 @@ func GetImpersonationToken(ctx context.Context, flags *PushFlags) (string, error
|
|||||||
|
|
||||||
rootRequest, err := ghClient.NewRequest("GET", enterpriseAPIPath, nil)
|
rootRequest, err := ghClient.NewRequest("GET", enterpriseAPIPath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "error constructing request for GitHub Enterprise client.")
|
return "", errors.Wrap(err, "error constructing request for GitHub Enterprise client")
|
||||||
}
|
}
|
||||||
rootResponse, err := ghClient.Do(ctx, rootRequest, nil)
|
rootResponse, err := ghClient.Do(ctx, rootRequest, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "error checking connectivity for GitHub Enterprise client.")
|
return "", errors.Wrap(err, "error checking connectivity for GitHub Enterprise client")
|
||||||
}
|
}
|
||||||
|
|
||||||
scopesHeader := rootResponse.Header.Get(xOAuthScopesHeader)
|
scopesHeader := rootResponse.Header.Get(xOAuthScopesHeader)
|
||||||
@@ -96,7 +96,7 @@ func GetImpersonationToken(ctx context.Context, flags *PushFlags) (string, error
|
|||||||
|
|
||||||
impersonationToken, _, err := ghClient.Admin.CreateUserImpersonation(ctx, flags.ActionsAdminUser, &github.ImpersonateUserOptions{Scopes: []string{minimumRepositoryScope, "workflow"}})
|
impersonationToken, _, err := ghClient.Admin.CreateUserImpersonation(ctx, flags.ActionsAdminUser, &github.ImpersonateUserOptions{Scopes: []string{minimumRepositoryScope, "workflow"}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "failed to impersonate Actions admin user.")
|
return "", errors.Wrap(err, "failed to impersonate Actions admin user")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("got the impersonation token for `%s` ...\n", flags.ActionsAdminUser)
|
fmt.Printf("got the impersonation token for `%s` ...\n", flags.ActionsAdminUser)
|
||||||
@@ -205,16 +205,19 @@ func getOrCreateGitHubRepo(ctx context.Context, client *github.Client, repoName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if repository already exists
|
// check if repository already exists
|
||||||
ghRepo, resp, err := client.Repositories.Get(ctx, ownerName, repoName)
|
var ghRepo *github.Repository
|
||||||
|
var resp *github.Response
|
||||||
if err == nil {
|
ghRepo, resp, err = client.Repositories.Get(ctx, ownerName, repoName)
|
||||||
fmt.Printf("Existing repo `%s/%s`\n", ownerName, repoName)
|
if err != nil {
|
||||||
} else if resp != nil && resp.StatusCode == 404 {
|
|
||||||
// repo not existing yet - try to create
|
// repo not existing yet - try to create
|
||||||
|
if resp != nil && resp.StatusCode == 404 {
|
||||||
|
fmt.Printf("repo `%s/%s` doesn't exist, attempting to create\n", ownerName, repoName)
|
||||||
|
|
||||||
visibility := github.String("public")
|
visibility := github.String("public")
|
||||||
if isAE {
|
if isAE {
|
||||||
visibility = github.String("internal")
|
visibility = github.String("internal")
|
||||||
}
|
}
|
||||||
|
|
||||||
repo := &github.Repository{
|
repo := &github.Repository{
|
||||||
Name: github.String(repoName),
|
Name: github.String(repoName),
|
||||||
HasIssues: github.Bool(false),
|
HasIssues: github.Bool(false),
|
||||||
@@ -225,18 +228,18 @@ func getOrCreateGitHubRepo(ctx context.Context, client *github.Client, repoName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ghRepo, _, err = client.Repositories.Create(ctx, createRepoOrgName, repo)
|
ghRepo, _, err = client.Repositories.Create(ctx, createRepoOrgName, repo)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
fmt.Printf("Created repo `%s/%s`\n", ownerName, repoName)
|
|
||||||
} else {
|
|
||||||
return nil, errors.Wrapf(err, "error creating repository %s/%s", ownerName, repoName)
|
|
||||||
}
|
|
||||||
} else if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "error creating repository %s/%s", ownerName, repoName)
|
return nil, errors.Wrapf(err, "error creating repository %s/%s", ownerName, repoName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ghRepo == nil {
|
fmt.Printf("created repo `%s/%s`\n", ownerName, repoName)
|
||||||
return nil, errors.New("error repository is nil")
|
return ghRepo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil, errors.Wrapf(err, "error creating repository %s/%s", ownerName, repoName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("found existing repo `%s/%s`\n", ownerName, repoName)
|
||||||
return ghRepo, nil
|
return ghRepo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func Test_extractSourceDest(t *testing.T) {
|
|||||||
assert.Equal(t, "src_owner/src_repo", src)
|
assert.Equal(t, "src_owner/src_repo", src)
|
||||||
assert.Equal(t, "dst_owner/dst_repo", dst)
|
assert.Equal(t, "dst_owner/dst_repo", dst)
|
||||||
|
|
||||||
src, dst, err = extractSourceDest("src_owner/src_repo:dst_owner/dst_repo:bogus/bogus")
|
_, _, err = extractSourceDest("src_owner/src_repo:dst_owner/dst_repo:bogus/bogus")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,24 +37,24 @@ func Test_validateNwo(t *testing.T) {
|
|||||||
assert.Equal(t, "a/b", nwo)
|
assert.Equal(t, "a/b", nwo)
|
||||||
|
|
||||||
// no slash separator
|
// no slash separator
|
||||||
nwo, err = validateNwo("bogus")
|
_, err = validateNwo("bogus")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// no owner
|
// no owner
|
||||||
nwo, err = validateNwo("/bogus")
|
_, err = validateNwo("/bogus")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// no repo name
|
// no repo name
|
||||||
nwo, err = validateNwo("bogus/")
|
_, err = validateNwo("bogus/")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
nwo, err = validateNwo("bogus whitespace/bogus")
|
_, err = validateNwo("bogus whitespace/bogus")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
nwo, err = validateNwo("bogus/bogus/bogus")
|
_, err = validateNwo("bogus/bogus/bogus")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// A separate destination is only permitted for "repo names", not NWOs.
|
// A separate destination is only permitted for "repo names", not NWOs.
|
||||||
nwo, err = validateNwo("owner/repo:bogus/bogus")
|
_, err = validateNwo("owner/repo:bogus/bogus")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user