Skip to content
Open
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
67 changes: 56 additions & 11 deletions tests/tap/t/099_zodan_mixed_version.pl
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@
# Env knobs:
# ZODAN_SCENARIO chain (default) or pair, see above
# ZODAN_N3_SRC chain only: node n3 joins from, n2 (default) or n1
# ZODAN_N12_VER name of the old build: v5 (default, built from
# origin/v5_STABLE), v6 (HEAD, gives an all-new-version
# ZODAN_N12_VER name of the old build: v5 (default, built from the
# v5_STABLE branch), v6 (HEAD, gives an all-new-version
# control run), or any other name together with ZODAN_N12_REF
# ZODAN_N12_REF git ref to build for ZODAN_N12_VER (e.g. v5.0.9); defaults
# exist for v5 and v6 only
# ZODAN_N12_REF branch, tag or commit id to build for ZODAN_N12_VER (e.g.
# v5.0.9); defaults exist for v5 and v6 only. A ref the
# checkout does not have is fetched from its origin remote.
# ZODAN_LOAD 1 = run pgbench load on the existing nodes while n3 joins
# ZODAN_SQL path to the zodan.sql to use (default: ../../samples/Z0DAN/zodan.sql)
# ZODAN_SCRATCH where add_node output and state dumps go (default: TESTLOGDIR or logs)
Expand Down Expand Up @@ -75,9 +76,21 @@ sub install_version {
die "ZODAN_SCENARIO must be chain or pair" unless $SCENARIO =~ /^(chain|pair)$/;
die "ZODAN_N3_SRC must be n1 or n2" unless $N3_SRC =~ /^n[12]$/;

my %BUILD_REF = (v5 => 'origin/v5_STABLE', v6 => 'HEAD');
my %BUILD_REF = (v5 => 'v5_STABLE', v6 => 'HEAD');
my $N12_REF = $ENV{ZODAN_N12_REF} // $BUILD_REF{$N12_VER}
// die "no default git ref for build '$N12_VER'; set ZODAN_N12_REF";
die "ZODAN_N12_REF '$N12_REF' does not look like a branch or tag name"
unless $N12_REF =~ m{^[A-Za-z0-9][A-Za-z0-9._/-]*$};

# Run a command given as a list (no shell) and return its stdout, chomped.
sub capture {
my (@cmd) = @_;
open(my $fh, '-|', @cmd) or die "cannot run @cmd: $!";
my $out = do { local $/; <$fh> };
close $fh;
chomp $out if defined $out;
return $out // '';
}

# Repository to build from: the CI checkout if present, else derive from cwd
# (tests run from tests/tap). Same rule as 014_rolling_upgrade.pl.
Expand All @@ -91,6 +104,36 @@ sub install_version {
die "SPOCK_REPO not found or missing Makefile: $SPOCK_REPO"
unless -d $SPOCK_REPO && -f "$SPOCK_REPO/Makefile";

# Resolve HEAD, a branch, a tag or a commit id in $SPOCK_REPO to (commit,
# what to fetch). A CI checkout is usually shallow, single-commit and
# detached, so a ref it does not have is fetched from its origin remote
# first. The second value is a full ref name, or the commit id itself when
# the input was one; either is what the build below fetches from $SPOCK_REPO.
sub resolve_build_ref {
my ($git_ref) = @_;
my $is_sha = $git_ref =~ /^[0-9a-f]{7,40}$/;
Comment thread
mason-sharp marked this conversation as resolved.
my @candidates = $git_ref eq 'HEAD' ? ('HEAD')
: $is_sha ? ($git_ref)
: ("refs/heads/$git_ref", "refs/tags/$git_ref", "refs/remotes/origin/$git_ref");
for my $attempt (1, 2) {
for my $ref (@candidates) {
my $commit = capture('git', '-C', $SPOCK_REPO, 'rev-parse', '--verify', '--quiet', "$ref^{commit}");
return ($commit, $ref =~ m{^refs/} ? $ref : $commit) if $commit;
}
last if $attempt == 2 || $git_ref eq 'HEAD';
diag("$SPOCK_REPO has no ref '$git_ref'; fetching it from origin");
if ($is_sha) {
system('git', '-C', $SPOCK_REPO, 'fetch', '--quiet', '--no-tags', '--depth=1', 'origin', $git_ref);
} else {
system('git', '-C', $SPOCK_REPO, 'fetch', '--quiet', '--no-tags', '--depth=1', 'origin',
"+refs/heads/$git_ref:refs/remotes/origin/$git_ref") == 0
or system('git', '-C', $SPOCK_REPO, 'fetch', '--quiet', '--depth=1', 'origin',
"+refs/tags/$git_ref:refs/tags/$git_ref");
}
}
die "cannot resolve git ref '$git_ref' in $SPOCK_REPO, and fetching it from origin failed";
}

# Build Spock at $git_ref into its own copy of the PostgreSQL install.
# The commit that was built is recorded in the tree; an existing tree is
# reused only when it holds the commit $git_ref resolves to now.
Expand All @@ -100,9 +143,7 @@ sub build_spock_tree {
my $pg_bin = "$tree/bin";
my $stamp = "$tree/.spock_commit";

my $commit = `git -C $SPOCK_REPO rev-parse --verify --quiet $git_ref`;
chomp $commit;
die "cannot resolve git ref '$git_ref' in $SPOCK_REPO" unless $commit;
my ($commit, $fetch_ref) = resolve_build_ref($git_ref);

if (-f $stamp) {
open(my $fh, '<', $stamp) or die "cannot read $stamp: $!";
Expand All @@ -115,7 +156,7 @@ sub build_spock_tree {
}

if ($git_ref eq 'HEAD') {
my $dirty = `git -C $SPOCK_REPO status --porcelain -- src sql include`;
my $dirty = capture('git', '-C', $SPOCK_REPO, 'status', '--porcelain', '--', 'src', 'sql', 'include');
diag("NOTE: uncommitted changes under src/, sql/ or include/ are not part of this build (it clones HEAD):\n$dirty")
if $dirty;
}
Expand All @@ -135,8 +176,12 @@ sub build_spock_tree {
my $sharedir = `$pg_bin/pg_config --sharedir`; chomp $sharedir;
unlink glob("$libdir/spock*.so"), glob("$sharedir/extension/spock*");

system_or_bail("git clone --quiet $SPOCK_REPO $build_dir");
system_or_bail("cd $build_dir && git checkout --quiet $git_ref") if $git_ref ne 'HEAD';
# Not a clone: git clone of a detached or shallow checkout has no branch
# to check out. Fetch the resolved ref into an empty repository instead
# and check out the exact commit.
system_or_bail('git', 'init', '--quiet', $build_dir);
system_or_bail('git', '-C', $build_dir, 'fetch', '--quiet', $SPOCK_REPO, $fetch_ref);
system_or_bail('git', '-C', $build_dir, 'checkout', '--quiet', $commit);
system_or_bail("cd $build_dir && make PG_CONFIG=$pg_bin/pg_config");
system_or_bail("cd $build_dir && make install PG_CONFIG=$pg_bin/pg_config");

Expand Down
Loading