Skip to content

Commit a107a0f

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 a107a0f

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-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_REF) # 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: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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_upstream_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 upstream_ref() {
31+
local downstream_commit="${1}"
32+
33+
local log
34+
log="$(git log -n 1 "${downstream_commit}")"
35+
36+
local -a upstream_repos
37+
mapfile -t upstream_repos < <(echo "${log}" | grep 'Upstream-repository:' | awk '{print $2}')
38+
39+
local -a upstream_commits
40+
mapfile -t upstream_commits < <(echo "${log}" | grep 'Upstream-commit:' | awk '{print $2}')
41+
42+
if (( ${#upstream_repos[@]} < 1 && ${#upstream_commits[@]} < 1 )); then
43+
# no upstream commit referenced
44+
return 0
45+
fi
46+
47+
if (( ${#upstream_repos[@]} > 1 )); then
48+
err "downstream staging commit ${downstream_commit} references more than one upstream repo:"
49+
err "${upstream_repos[@]}"
50+
err "staging commits may only reference a single upstream repo"
51+
return 1
52+
fi
53+
54+
if (( ${#upstream_commits[@]} > 1 )); then
55+
err "downstream staging commit ${downstream_commit} references more than one upstream commit:"
56+
err "${upstream_commits[@]}"
57+
err "staging commits may only reference a single upstream commit"
58+
return 1
59+
fi
60+
61+
if git branch -r --contains "${upstream_commits[0]}" | grep -vq "${upstream_repos[0]}/.*"; then
62+
err "downstream staging commit ${downstream_commit} references upstream commit ${upstream_commits[0]} that doesn't exist in ${upstream_repos[0]}"
63+
err "staging commits must reference a repository containing the given upstream commit"
64+
return 1
65+
fi
66+
67+
echo "${upstream_repos[0]}"
68+
echo "${upstream_commits[0]}"
69+
}
70+
71+
function fetch_remotes() {
72+
local -a remotes
73+
remotes=(
74+
'api'
75+
'operator-registry'
76+
'operator-lifecycle-manager'
77+
)
78+
for r in "${remotes[@]}"; do
79+
local url
80+
url="https://github.com/operator-framework/${r}.git"
81+
82+
git remote add "${r}" "${url}" || git remote set-url "${r}" "${url}"
83+
git fetch "${r}" master
84+
done
85+
}
86+
87+
function main() {
88+
fetch_remotes || { err "failed to fetch remotes" && exit 1; }
89+
90+
local target_branch="${1:-master}"
91+
92+
# get all commits we're introducing into the target branch
93+
local -a new_commits
94+
mapfile -t new_commits < <(git rev-list HEAD "^${target_branch}")
95+
96+
local -a sr
97+
for commit in "${new_commits[@]}"; do
98+
info "verifying ${commit:0:7}"
99+
100+
mapfile -t sr < <(upstream_ref "${commit}" || exit 1)
101+
if (( ${#sr[@]} < 2 )); then # the ref contains a tuple if the values were properly parsed from the commit message
102+
# couldn't find staging cherry-pick reference in the commit message
103+
# assume it's downstream-only commit
104+
info "${commit:0:7} does not reference upstream commit, verifying as downstream-only"
105+
else
106+
# found staging cherry-pick reference in commit message
107+
# verify as an upstream sync
108+
info "${commit:0:7} references upstream commit (${sr[*]}), verifying as upstream sync"
109+
verify_upstream_sync "${sr[0]}" "${commit}"
110+
fi
111+
112+
done
113+
}
114+
115+
main "$@"

0 commit comments

Comments
 (0)