Skip to content

Commit 69bbeb0

Browse files
committed
chore: add verify-commits make target
Add a Make target that verifies commits added between the current head and master: - reference only one upstream, if any - if referencing an upstream, only make changes to the vendor, manifests, and/or respective staging directory
1 parent 06abc61 commit 69bbeb0

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ verify-manifests: manifests
147147
verify-nested-vendor:
148148
./scripts/check-staging-vendor.sh
149149

150+
.PHONY: verify-commits
151+
verify-commits:
152+
./scripts/verify_commits.sh $(PULL_BASE_SHA) # see https://github.com/kubernetes/test-infra/blob/master/prow/jobs.md#job-environment-variables
153+
150154
.PHONY: verify
151155
verify:
152156
echo "Checking for unstaged root vendor changes"
@@ -155,6 +159,8 @@ verify:
155159
$(MAKE) verify-manifests
156160
echo "Checking for unsynced nested [go.mod,go.sum] files"
157161
$(MAKE) verify-nested-vendor
162+
echo "Checking commit integrity"
163+
$(MAKE) verify-commits
158164

159165
.PHONY: help
160166
help: ## Display this help.

scripts/verify_commits.sh

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
function err() {
8+
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
9+
}
10+
11+
function info() {
12+
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*"
13+
}
14+
15+
function verify_staging_sync() {
16+
local remote="${1}"
17+
local downstream_commit="${2}"
18+
local staging_dir="staging/${remote}"
19+
20+
local outside_staging
21+
outside_staging="$(git show --name-only "${downstream_commit}" -- ":!${staging_dir}" ':!vendor :!manifests')"
22+
if [[ -n "${outside_staging}" ]]; then
23+
err "downstream staging commit ${downstream_commit} changes files outside of ${staging_dir}, vendor, and manifests directories"
24+
err "${outside_staging}"
25+
err "hint: factor out changes to these directories into a standalone commit"
26+
return 1
27+
fi
28+
}
29+
30+
function verify_downstream_only() {
31+
local downstream_commit="${1}"
32+
33+
local inside_staging
34+
inside_staging="$(git show --name-only "${downstream_commit}" -- staging)"
35+
if [[ -n "${inside_staging}" ]]; then
36+
err "downstream non-staging commit ${downstream_commit} changes staging"
37+
err "${inside_staging}"
38+
err "only staging commits (i.e. from an upstream cherry-pick) may change staging"
39+
40+
return 1
41+
fi
42+
}
43+
44+
function upstream_ref() {
45+
local downstream_commit="${1}"
46+
47+
local log
48+
log="$(git log -n 1 "${downstream_commit}")"
49+
50+
local -a upstream_repos
51+
mapfile -t upstream_repos < <(echo "${log}" | grep 'Upstream-repository:' | awk '{print $2}')
52+
53+
local -a upstream_commits
54+
mapfile -t upstream_commits < <(echo "${log}" | grep 'Upstream-commit:' | awk '{print $2}')
55+
56+
if (( ${#upstream_repos[@]} < 1 && ${#upstream_commits[@]} < 1 )); then
57+
# no upstream commit referenced
58+
return 0
59+
fi
60+
61+
62+
local invalid
63+
if (( ${#upstream_repos[@]} != 1 )); then
64+
err "downstream staging commit ${downstream_commit} references an invalid number of repos:"
65+
err "${upstream_repos[@]}"
66+
err "staging commits must reference reference a single upstream repo"
67+
invalid=true
68+
fi
69+
70+
if (( ${#upstream_commits[@]} != 1 )); then
71+
err "downstream staging commit ${downstream_commit} references an invalid number of upstream commits:"
72+
err "${upstream_commits[@]}"
73+
err "staging commits must reference a single upstream commit"
74+
invalid=true
75+
fi
76+
77+
if [[ "${invalid}" == true ]]; then
78+
return 1
79+
fi
80+
81+
if git branch -r --contains "${upstream_commits[0]}" | grep -vq "${upstream_repos[0]}/.*"; then
82+
err "downstream staging commit ${downstream_commit} references upstream commit ${upstream_commits[0]} that doesn't exist in ${upstream_repos[0]}"
83+
err "staging commits must reference a repository containing the given upstream commit"
84+
return 1
85+
fi
86+
87+
echo "${upstream_repos[0]}"
88+
echo "${upstream_commits[0]}"
89+
}
90+
91+
function fetch_remotes() {
92+
local -a remotes
93+
remotes=(
94+
'api'
95+
'operator-registry'
96+
'operator-lifecycle-manager'
97+
)
98+
for r in "${remotes[@]}"; do
99+
local url
100+
url="https://github.com/operator-framework/${r}.git"
101+
102+
git remote add "${r}" "${url}" 2>/dev/null || git remote set-url "${r}" "${url}"
103+
git fetch -q "${r}" master
104+
done
105+
}
106+
107+
function main() {
108+
fetch_remotes || { err "failed to fetch remotes" && exit 1; }
109+
110+
local target_branch="${1:-master}"
111+
112+
# get all commits we're introducing into the target branch
113+
local -a new_commits
114+
mapfile -t new_commits < <(git rev-list --no-merges HEAD "^${target_branch}")
115+
info "detected ${#new_commits[@]} commit(s) to verify"
116+
117+
local -a sr
118+
local short
119+
for commit in "${new_commits[@]}"; do
120+
short="${commit:0:7}"
121+
info "verifying ${short}..."
122+
info "$(git log -n 1 "${commit}")"
123+
124+
mapfile -t sr < <(upstream_ref "${commit}" || exit 1)
125+
if (( ${#sr[@]} < 2 )); then # the ref contains a tuple if the values were properly parsed from the commit message
126+
# couldn't find upstream cherry-pick reference in the commit message
127+
# assume it's downstream-only commit
128+
info "${short} does not reference upstream commit, verifying as downstream-only"
129+
verify_downstream_only "${commit}" || exit 1
130+
else
131+
# found upstream cherry-pick reference in commit message
132+
# verify as an upstream sync
133+
info "${short} references upstream commit (${sr[*]}), verifying as upstream staging sync"
134+
verify_staging_sync "${sr[0]}" "${commit}" || exit 1
135+
fi
136+
137+
done
138+
}
139+
140+
main "$@"

0 commit comments

Comments
 (0)