#!/usr/bin/env bash # # Non-regression test for the POSTIT_GIT_TAG handling in debian/rules. # # Background: a previous version of override_dh_auto_build used # `git clone --branch ` to fetch upstream. That only works for # branch names; feeding it an annotated tag (e.g. 1.0.1-rc02) failed # with "La branche distante 1.0.1-rc02 n'a pas ete trouvee" and # aborted the whole package build. # # This test pins the upstream-fetch logic against the *real* # pazof/yavsc remote on GitHub: tags like 1.0.1-rc01 exist there, # so we can verify both branches and tags resolve to the expected # commit without spinning up a fake local server (the local Git # transport handles shallow tag fetches differently from smart-http, # so a local-only test would be misleading). # # Scope: deliberately does NOT run dpkg-buildpackage / dotnet # publish / dh_install. Those stages are exercised manually per # release; this test pins the Git mechanics which previously # regressed silently until the next tag bump. set -euo pipefail TEST_NAME="$(basename "$0")" # Skip on environments without network access (offline CI runners, # dev sandboxes without GitHub egress). The test is a non-regression # guard, not a connectivity test; failing because GitHub is down # would mask the signal we actually care about. if [ "${SKIP_NETWORK_TESTS:-0}" = "1" ]; then echo "$TEST_NAME: SKIP -- SKIP_NETWORK_TESTS=1" exit 0 fi WORK="$(mktemp -d -t postit-fetch-test.XXXXXX)" trap 'rm -rf "$WORK"' EXIT # Real remote. The branch + tag values below MUST exist for the # test to pass; if pazof retags the repo, bump them. Anchored on # commits known to be immutable: 1.0.0 is the initial release, # 1.0.1-rc01 is the rc Paul shipped after the OIDC fixes. REMOTE_URL="https://github.com/pazof/yavsc.git" TEST_BRANCH="main" TEST_TAG="1.0.1-rc01" # Expected commits from `git ls-remote`. Computed at test time so we # don't have to update this script every time the repo moves; we # just assert "whatever HEAD I end up on must match what `git # ls-remote` says the ref points at". EXPECTED_BRANCH_SHA="$(git ls-remote "$REMOTE_URL" "refs/heads/$TEST_BRANCH" | awk '{print $1}')" EXPECTED_TAG_SHA="$(git ls-remote "$REMOTE_URL" "refs/tags/$TEST_TAG" | awk '{print $1}')" if [ -z "$EXPECTED_BRANCH_SHA" ] || [ -z "$EXPECTED_TAG_SHA" ]; then echo "$TEST_NAME: SKIP -- refs not present on remote (branch=$EXPECTED_BRANCH_SHA tag=$EXPECTED_TAG_SHA)" exit 0 fi # Helper copied verbatim from debian/rules. If debian/rules drifts, # this copy must drift with it -- that is the point of pinning the # logic in a test. fetch_upstream() { local url="$1" ref="$2" dest="$3" mkdir -p "$(dirname "$dest")" if [ ! -d "$dest/.git" ]; then git init -q "$dest" git -C "$dest" remote add origin "$url" fi git -C "$dest" fetch --depth=1 origin "$ref" git -C "$dest" checkout -q FETCH_HEAD } # --- Case 1: POSTIT_GIT_TAG points at an annotated tag. ---------- # This is the regression case. Before the fix, this failed with # "La branche distante n'a pas ete trouvee". DEST="$WORK/yavsc-src-tag" rm -rf "$DEST" if ! fetch_upstream "$REMOTE_URL" "$TEST_TAG" "$DEST" 2> "$WORK/fetch-tag.err"; then echo "$TEST_NAME: FAIL -- fetch_upstream errored on tag '$TEST_TAG'" sed 's/^/ /' "$WORK/fetch-tag.err" exit 1 fi GOT="$(git -C "$DEST" rev-parse HEAD)" if [ "$GOT" != "$EXPECTED_TAG_SHA" ]; then echo "$TEST_NAME: FAIL -- tag '$TEST_TAG' resolved to '$GOT', expected '$EXPECTED_TAG_SHA'" exit 1 fi # A shallow clone cannot always determine "exact tag match" because # the tag-object might not have been fetched. The commit-hash match # above is the authoritative check; the describe call is a softer # sanity signal that we still log but do not gate on. DESCRIBED="$(git -C "$DEST" describe --tags --exact-match HEAD 2>/dev/null || echo '')" echo "$TEST_NAME: tag '$TEST_TAG' -> $GOT (describe: $DESCRIBED)" # --- Case 2: POSTIT_GIT_TAG points at a branch. ------------------ # Branches must keep working; this is the path the old code was # originally written for and we don't want to break it. DEST="$WORK/yavsc-src-branch" rm -rf "$DEST" if ! fetch_upstream "$REMOTE_URL" "$TEST_BRANCH" "$DEST" 2> "$WORK/fetch-branch.err"; then echo "$TEST_NAME: FAIL -- fetch_upstream errored on branch '$TEST_BRANCH'" sed 's/^/ /' "$WORK/fetch-branch.err" exit 1 fi GOT="$(git -C "$DEST" rev-parse HEAD)" if [ "$GOT" != "$EXPECTED_BRANCH_SHA" ]; then echo "$TEST_NAME: FAIL -- branch '$TEST_BRANCH' resolved to '$GOT', expected '$EXPECTED_BRANCH_SHA'" exit 1 fi echo "$TEST_NAME: branch '$TEST_BRANCH' -> $GOT" # --- Case 3: existing .git directory is reused (the second-build # fast path). The build dir persists across builds, so the helper # must not re-init when .git is already there. We populate the # branch first, then refetch to the tag without nuking the # existing origin remote. DEST="$WORK/yavsc-src-reuse" rm -rf "$DEST" fetch_upstream "$REMOTE_URL" "$TEST_BRANCH" "$DEST" >/dev/null 2>&1 ORIG_REMOTE="$(git -C "$DEST" remote get-url origin)" if ! fetch_upstream "$REMOTE_URL" "$TEST_TAG" "$DEST" >/dev/null 2> "$WORK/fetch-reuse.err"; then echo "$TEST_NAME: FAIL -- second fetch on existing .git errored" sed 's/^/ /' "$WORK/fetch-reuse.err" exit 1 fi if [ "$(git -C "$DEST" remote get-url origin)" != "$ORIG_REMOTE" ]; then echo "$TEST_NAME: FAIL -- remote origin was clobbered on reuse" exit 1 fi GOT="$(git -C "$DEST" rev-parse HEAD)" if [ "$GOT" != "$EXPECTED_TAG_SHA" ]; then echo "$TEST_NAME: FAIL -- reuse case tag fetch landed on '$GOT', expected '$EXPECTED_TAG_SHA'" exit 1 fi echo "$TEST_NAME: reuse case tag '$TEST_TAG' -> $GOT (remote preserved)" # --- Case 4: POSTIT_GIT_TAG is a tag that exists only on a local # repo, fetched via file://. This is the Paul workflow for staging # an RC: `git tag 1.0.1-rc02` on ~/Workspace/yavsc, then # `make POSTIT_GIT_URL=file:///home/paul/Workspace/yavsc # POSTIT_GIT_TAG=1.0.1-rc02` to build the .deb before # pushing the tag to github.com/pazof/yavsc. The fix must support # this without requiring the tag to be on a public remote first. LOCAL_REPO="$WORK/local-repo" LOCAL_TAG="test-local-rc-$$" # Use ^{commit} to dereference the tag-object to the underlying # commit; that's what git checkout FETCH_HEAD lands on. LOCAL_TAG_SHA="$(mktemp -u XXXXXXXXXXXX)" git init -q "$LOCAL_REPO" git -C "$LOCAL_REPO" -c user.email=test@test.local -c user.name=test \ commit --allow-empty -q -m "local seed" git -C "$LOCAL_REPO" tag -a "$LOCAL_TAG" -m "local-only tag" LOCAL_TAG_SHA="$(git -C "$LOCAL_REPO" rev-parse "$LOCAL_TAG^{commit}")" DEST="$WORK/yavsc-src-local" rm -rf "$DEST" if ! fetch_upstream "file://$LOCAL_REPO" "$LOCAL_TAG" "$DEST" 2> "$WORK/fetch-local.err"; then echo "$TEST_NAME: FAIL -- fetch_upstream errored on local-only tag '$LOCAL_TAG'" sed 's/^/ /' "$WORK/fetch-local.err" exit 1 fi GOT="$(git -C "$DEST" rev-parse HEAD)" if [ "$GOT" != "$LOCAL_TAG_SHA" ]; then echo "$TEST_NAME: FAIL -- local tag '$LOCAL_TAG' resolved to '$GOT', expected '$LOCAL_TAG_SHA'" exit 1 fi echo "$TEST_NAME: local tag '$LOCAL_TAG' via file:// -> $GOT" echo "$TEST_NAME: PASS -- tag, branch, reuse, and local-only tag all resolve correctly"