Skip to content

Commit 8a0800b

Browse files
author
Matthew Jackson
committed
ci: wait for the terraform-provider release on a fan-out dispatch
Same ordering race as pulumi-busbar. The busbar fan-out wakes every downstream repo simultaneously, but the terraform-provider release this repo pins is cut from that same fan-out and lands minutes later, so a dispatch-triggered run resolved a stale 'latest', concluded nothing to do and went green while the pin stayed behind. It was masked here because the run was failing in make generate first; with that fixed the race would have been the next thing to bite. A repository_dispatch run now polls for a newer sibling release for a bounded period, and if none appears it ends on a warning rather than a quiet success.
1 parent 2898b36 commit 8a0800b

1 file changed

Lines changed: 56 additions & 14 deletions

File tree

.github/workflows/release-on-upstream.yml

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
# TERRAFORM_PROVIDER_VERSION, and the build embeds that provider release's linux binary + generates
55
# CRDs from its schema. That pin IS this repo's record of what it was last built against.
66
#
7-
# The busbar-core upstream-release dispatch is only a WAKE signal here this repo does not consume
7+
# The busbar-core upstream-release dispatch is only a WAKE signal here - this repo does not consume
88
# busbar core directly. On any trigger this resolves terraform-provider-busbar's LATEST release and
9-
# only proceeds if it is newer than the current pin. That also fixes the fan-out ordering race: when
10-
# busbar core dispatches to the whole fleet at once, the terraform-provider release may not exist yet
11-
# — we simply no-op, and the daily cron (or the next dispatch) self-heals once it does. Runaway-safe:
12-
# an idle day, or an already-ingested provider release, is a no-op, never a spurious re-cut.
9+
# only proceeds if it is newer than the current pin. Runaway-safe: an idle day, or an
10+
# already-ingested provider release, is a no-op, never a spurious re-cut.
11+
#
12+
# FLEET FAN-OUT ORDERING: busbar core dispatches to the whole fleet at once, so on a dispatch the
13+
# terraform-provider release usually does not exist yet. A dispatch-triggered run therefore POLLS for
14+
# the sibling release for a bounded time and proceeds as soon as it appears; if it never appears the
15+
# run ends on a loud warning rather than a quiet green "nothing to do".
1316
#
1417
# On a real advance this re-pins TERRAFORM_PROVIDER_VERSION, `make generate`s the CRDs/examples,
1518
# bumps THIS repo's own v* tag, commits, and pushes the tag — which fires publish-provider-package.yml
@@ -47,6 +50,10 @@ env:
4750
# starting its own v0.1.0 line (mixed-model: wrappers keep independent semver, they do NOT mirror
4851
# busbar's version).
4952
SEED_VERSION: v0.1.0
53+
# How long a repository_dispatch wake waits for terraform-provider-busbar's own release to show up
54+
# before giving up (see the ordering-race note in the resolve step).
55+
UPSTREAM_WAIT_SECONDS: "1200"
56+
UPSTREAM_POLL_SECONDS: "30"
5057

5158
jobs:
5259
cut:
@@ -80,28 +87,63 @@ jobs:
8087
set -euo pipefail
8188
cur_pin="$(awk -F'=' '/^export TERRAFORM_PROVIDER_VERSION[[:space:]]*\?=/{gsub(/[[:space:]]/,"",$2); print $2; exit}' Makefile)"
8289
echo "current TERRAFORM_PROVIDER_VERSION pin: ${cur_pin:-<none>}"
90+
8391
# Always resolve the upstream terraform-provider's LATEST release (the dispatch payload is
8492
# just a wake signal; our real dependency is the TF provider, not busbar core).
85-
target_tag="$(gh api repos/GetBusbar/terraform-provider-busbar/releases/latest --jq .tag_name 2>/dev/null || true)"
86-
target_ver="${target_tag#v}"
87-
echo "terraform-provider-busbar latest release: ${target_tag:-none} (version ${target_ver:-none})"
88-
89-
force=no
90-
[ "$EVENT_NAME" = workflow_dispatch ] && force=yes
93+
latest_ver() {
94+
local t
95+
t="$(gh api repos/GetBusbar/terraform-provider-busbar/releases/latest --jq .tag_name 2>/dev/null || true)"
96+
printf '%s' "${t#v}"
97+
}
98+
is_newer() { # is_newer <candidate> <current> -> 0 when candidate > current
99+
[ -n "$1" ] || return 1
100+
[ "$1" != "$2" ] || return 1
101+
[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | tail -1)" = "$1" ]
102+
}
103+
104+
target_ver="$(latest_ver)"
105+
echo "terraform-provider-busbar latest release: ${target_ver:-none}"
91106
92107
pin_stale=no
93-
if [ -n "$target_ver" ] && [ "$target_ver" != "$cur_pin" ]; then
94-
newest="$(printf '%s\n%s\n' "$cur_pin" "$target_ver" | sort -V | tail -1)"
95-
[ "$newest" = "$target_ver" ] && pin_stale=yes
108+
is_newer "$target_ver" "$cur_pin" && pin_stale=yes
109+
110+
# ORDERING RACE. GetBusbar/busbar's notify-downstream job wakes the whole fleet at once, but
111+
# terraform-provider-busbar cuts its own release from that same fan-out, so on a dispatch
112+
# the sibling release we depend on is routinely published minutes AFTER we are woken (for
113+
# busbar 1.5.3 it was about five and a half minutes later). Resolving "latest" a single time
114+
# and reporting a green "nothing to do" hides that. Wait for it, bounded, instead.
115+
if [ "$EVENT_NAME" = repository_dispatch ] && [ "$pin_stale" = no ]; then
116+
echo "::notice::dispatch-triggered and no newer terraform-provider yet -> waiting up to ${UPSTREAM_WAIT_SECONDS}s for the sibling release"
117+
waited=0
118+
while [ "$waited" -lt "$UPSTREAM_WAIT_SECONDS" ]; do
119+
sleep "$UPSTREAM_POLL_SECONDS"
120+
waited=$((waited + UPSTREAM_POLL_SECONDS))
121+
probe="$(latest_ver)"
122+
echo " +${waited}s: latest=${probe:-none}"
123+
if is_newer "$probe" "$cur_pin"; then
124+
target_ver="$probe"
125+
pin_stale=yes
126+
echo "::notice::terraform-provider ${probe} appeared after ${waited}s of waiting -> proceeding"
127+
break
128+
fi
129+
done
96130
fi
97131
132+
force=no
133+
[ "$EVENT_NAME" = workflow_dispatch ] && force=yes
134+
98135
should_cut=no
99136
if [ "$force" = yes ]; then
100137
should_cut=yes
101138
echo "::notice::manual workflow_dispatch -> cutting a release (pin_stale=${pin_stale})"
102139
elif [ "$pin_stale" = yes ]; then
103140
should_cut=yes
104141
echo "::notice::terraform-provider advanced (pinned=${cur_pin} -> ${target_ver}) -> cutting a release"
142+
elif [ "$EVENT_NAME" = repository_dispatch ]; then
143+
# An upstream-release dispatch that still ends in "nothing to do" after waiting means the
144+
# fan-out fired too early or the sibling release failed. Do not report that as a quiet
145+
# green; the daily cron still self-heals, but this has to be visible in the run list.
146+
echo "::warning title=upstream-release dispatch produced no release::woken by an upstream-release dispatch but terraform-provider-busbar is still at ${target_ver:-none} (pin ${cur_pin:-none}) after waiting ${UPSTREAM_WAIT_SECONDS}s. Either the sibling release failed or the fan-out fired too early. This repo is NOT refreshed; the daily cron will retry."
105147
else
106148
echo "::notice::no newer terraform-provider (pinned=${cur_pin:-none}, latest=${target_ver:-none}) -> nothing to do"
107149
fi

0 commit comments

Comments
 (0)