vouchington-tooling 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vouchington-tooling",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Vouchington CLI and extractable tooling libraries.",
|
|
5
5
|
"homepage": "https://github.com/vouchington/vouchington-tooling/tree/main/packages/vouchington-tooling#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
usage() {
|
|
5
|
+
echo "usage: backfill-slash-release-tags.sh --package NAME [--package NAME]... [--dry-run] [--write] [--push] [--remote NAME]" >&2
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
packages=()
|
|
9
|
+
explicit_dry=0
|
|
10
|
+
do_write=0
|
|
11
|
+
do_push=0
|
|
12
|
+
remote=origin
|
|
13
|
+
|
|
14
|
+
while [ $# -gt 0 ]; do
|
|
15
|
+
case "$1" in
|
|
16
|
+
--package)
|
|
17
|
+
[ $# -ge 2 ] || { usage; exit 2; }
|
|
18
|
+
packages+=("$2")
|
|
19
|
+
shift 2
|
|
20
|
+
;;
|
|
21
|
+
--dry-run)
|
|
22
|
+
explicit_dry=1
|
|
23
|
+
shift
|
|
24
|
+
;;
|
|
25
|
+
--write)
|
|
26
|
+
do_write=1
|
|
27
|
+
shift
|
|
28
|
+
;;
|
|
29
|
+
--push)
|
|
30
|
+
do_push=1
|
|
31
|
+
shift
|
|
32
|
+
;;
|
|
33
|
+
--remote)
|
|
34
|
+
[ $# -ge 2 ] || { usage; exit 2; }
|
|
35
|
+
remote="$2"
|
|
36
|
+
shift 2
|
|
37
|
+
;;
|
|
38
|
+
-h | --help)
|
|
39
|
+
usage
|
|
40
|
+
exit 2
|
|
41
|
+
;;
|
|
42
|
+
*)
|
|
43
|
+
usage
|
|
44
|
+
exit 2
|
|
45
|
+
;;
|
|
46
|
+
esac
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
if [ "${#packages[@]}" -eq 0 ]; then
|
|
50
|
+
usage
|
|
51
|
+
exit 2
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
if [ "$explicit_dry" -eq 1 ] && { [ "$do_write" -eq 1 ] || [ "$do_push" -eq 1 ]; }; then
|
|
55
|
+
echo "cannot combine --dry-run with --write or --push" >&2
|
|
56
|
+
exit 2
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
dry_run=1
|
|
60
|
+
if [ "$do_write" -eq 1 ] || [ "$do_push" -eq 1 ]; then
|
|
61
|
+
dry_run=0
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
semver='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'
|
|
65
|
+
push_refs=()
|
|
66
|
+
|
|
67
|
+
for package in "${packages[@]}"; do
|
|
68
|
+
if [[ ! "$package" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
|
69
|
+
echo "invalid package name: ${package}" >&2
|
|
70
|
+
exit 2
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
while IFS= read -r hyphen_tag; do
|
|
74
|
+
[ -n "$hyphen_tag" ] || continue
|
|
75
|
+
version="${hyphen_tag#"${package}-v"}"
|
|
76
|
+
if [[ ! "$version" =~ $semver ]]; then
|
|
77
|
+
echo "hyphen tag ${hyphen_tag} is not <package>-v<semver>" >&2
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
slash_tag="${package}/v${version}"
|
|
82
|
+
commit="$(git rev-parse "refs/tags/${hyphen_tag}^{commit}")"
|
|
83
|
+
|
|
84
|
+
if git rev-parse -q --verify "refs/tags/${slash_tag}" >/dev/null; then
|
|
85
|
+
existing="$(git rev-parse "refs/tags/${slash_tag}^{commit}")"
|
|
86
|
+
if [ "$existing" != "$commit" ]; then
|
|
87
|
+
echo "slash tag ${slash_tag} points at ${existing}, expected ${commit}" >&2
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
echo "skip ${slash_tag} (already at ${commit})"
|
|
91
|
+
continue
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
echo "create ${slash_tag} -> ${commit}"
|
|
95
|
+
if [ "$dry_run" -eq 0 ]; then
|
|
96
|
+
git tag -a "${slash_tag}" -m "${package} v${version}" "$commit"
|
|
97
|
+
push_refs+=("refs/tags/${slash_tag}")
|
|
98
|
+
fi
|
|
99
|
+
done < <(git tag --list "${package}-v*")
|
|
100
|
+
done
|
|
101
|
+
|
|
102
|
+
if [ "$do_push" -eq 0 ]; then
|
|
103
|
+
exit 0
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if [ "${#push_refs[@]}" -eq 0 ]; then
|
|
107
|
+
echo "nothing to push"
|
|
108
|
+
exit 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
git push --atomic "$remote" "${push_refs[@]}"
|
|
@@ -12,25 +12,32 @@ merge.
|
|
|
12
12
|
|
|
13
13
|
A stack is a sequence of branches, each submitted as its own pull request, where every PR but the
|
|
14
14
|
bottom-most one targets the PR below it as its base branch instead of targeting the default branch
|
|
15
|
-
directly.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
directly. GitHub tracks a chain like this as a single stack, and its own documentation on merging
|
|
16
|
+
stacked pull requests is explicit about what a merge then does: "the selected pull request and all
|
|
17
|
+
unmerged pull requests below it land on the base branch together as a single operation, ordered
|
|
18
|
+
from the bottom up," and merging one is only possible once everything below it already satisfies
|
|
19
|
+
whatever this repository requires to merge — you cannot merge an isolated middle layer on its own.
|
|
20
|
+
That is dedicated stack-merge behavior, not the ordinary single-branch merge semantics a generic
|
|
21
|
+
"merge this PR" action assumes, and it comes with its own restrictions: GitHub does not support
|
|
22
|
+
auto-merge for stacked pull requests at all, and a plain, non-stack-aware merge mechanism is not
|
|
23
|
+
guaranteed to reproduce this cascade correctly. A mid-stack PR's base ref being an unmerged branch,
|
|
24
|
+
not the default branch, is the sign to slow down and confirm the merge path in use actually
|
|
25
|
+
understands stacks before treating it as routine.
|
|
20
26
|
|
|
21
27
|
Drain a stack from the bottom, one layer at a time, merging each bottom-most layer as soon as it
|
|
22
28
|
becomes ready rather than waiting for every layer above it to be ready first. A stack should stay as
|
|
23
29
|
short as it can be: every layer that remains unmerged keeps accumulating rebase surface, CI cost,
|
|
24
30
|
and drift against the default branch, and that cost compounds for every layer still stacked above
|
|
25
|
-
it.
|
|
31
|
+
it. Because stacked pull requests do not auto-merge, draining only happens through a deliberate
|
|
32
|
+
merge action taken each time a layer becomes ready — nothing lands on its own just because it is
|
|
33
|
+
ready.
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
not an arbitrary or more convenient one.
|
|
35
|
+
Merging a given layer lands that layer and every unmerged layer below it in the same operation, so
|
|
36
|
+
whatever merge target is used must name the bottom-most unmerged layer specifically, not a higher
|
|
37
|
+
one, to land exactly the increment intended for that drain step: naming a higher layer either merges
|
|
38
|
+
more than intended, when everything below also happens to be ready, or is simply unavailable, when
|
|
39
|
+
it is not. Once a layer merges, GitHub retargets the next unmerged layer onto the default branch
|
|
40
|
+
directly, so it becomes the new bottom — treat it the same way on the next drain step.
|
|
34
41
|
|
|
35
42
|
When a drain stalls — something on the stack needs human attention, or a layer closes without
|
|
36
43
|
merging — but the bottom-most layer is otherwise ready to merge, stop before yielding: report the
|