#!/usr/bin/env bash script/build 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=$! 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() { bin/actions-sync version \ &> $OUTPUT || fail $1 } function pull() { bin/actions-sync pull \ --cache-dir "test/tmp/cache" \ --source-url "git://localhost:$SRC_GIT_DAEMON_PORT" \ "$1" "$2" \ &> $OUTPUT || fail $3 } function push() { bin/actions-sync 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() { bin/actions-sync 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() { bin/actions-sync 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() { bin/actions-sync 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 } test_version before_suite test_pull test_push test_sync