forked from jtmullen/submodule-branch-check-action
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathentrypoint.sh
executable file
·231 lines (195 loc) · 9.34 KB
/
entrypoint.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#!/bin/bash
startrev=`git rev-parse HEAD`
startgitfetchsetting=`git config --get remote.origin.fetch`
restoreState () {
echo "::group::Restoring Repo State"
cd "${GITHUB_WORKSPACE}"
git config remote.origin.fetch "${startgitfetchsetting}"
git checkout $startrev
git submodule update
echo "::endgroup::"
}
error () {
echo "fails=error" >> $GITHUB_OUTPUT
echo "::error::$1"
restoreState
exit 1
}
# When a new submodule is added we have no way to check for progression. In this case we will skip that check (instead of failing it)
newSubmodule=false
newSubmoduleWarning() {
newSubmodule=true
echo "::warning::Submodule $1 does not exist on the base branch/commit; Cannot do progression check for new submodules"
}
## Path to JSON Payload of the Github Event Info
EVENT_PATH="${GITHUB_EVENT_PATH}"
## Check for override of event path - used for tests
if [[ ! -z "${INPUT_EVENT_PATH}" ]]; then
EVENT_PATH="${INPUT_EVENT_PATH}"
## Put warning here as this probably should not be used outside testing
echo "::warning::Github Event Payload Path Overwritten. Only intended for testing use."
fi
echo "::group::Setup"
cd "${GITHUB_WORKSPACE}" || error "__Line:${LINENO}__Error: Cannot change directory to Github Workspace"
REPO=`jq -r ".repository.full_name" "${EVENT_PATH}"`
## Get all the info about this push or pr event we need to check the submodule
isPR=false
if [[ $(jq -r ".pull_request.head.ref" "${EVENT_PATH}") != "null" ]]; then
PR=`jq -r ".number" "${EVENT_PATH}"`
PR_BRANCH=`jq -r ".pull_request.head.ref" "${EVENT_PATH}"`
BASE_BRANCH=`jq -r ".pull_request.base.ref" "${EVENT_PATH}"`
USER=`jq -r ".pull_request.user.login" "${EVENT_PATH}"`
git fetch origin "${PR_BRANCH}" --recurse-submodules=no --depth 1 || error "__Line:${LINENO}__Error: Could not fetch tip of ${PR_BRANCH}"
git fetch origin "${BASE_BRANCH}" --recurse-submodules=no --depth 1 || error "__Line:${LINENO}__Error: Could not fetch tip of ${BASE_BRANCH}"
TO_HASH=`git rev-parse origin/${PR_BRANCH}`
FROM_HASH=`git rev-parse origin/${BASE_BRANCH}`
echo "Run for PR # ${PR} of ${PR_BRANCH} into ${BASE_BRANCH} on ${REPO} by ${USER}"
echo "Hash ${TO_HASH} into ${FROM_HASH}"
isPR=true
elif [[ $(jq -r ".after" "${EVENT_PATH}") != "null" ]]; then
TO_HASH=`jq -r ".after" "${EVENT_PATH}"`
FROM_HASH=`jq -r ".before" "${EVENT_PATH}"`
BRANCH_NAME=`jq -r ".ref" "${EVENT_PATH}"`
BASE_BRANCH="${FROM_HASH}"
PR_BRANCH="${TO_HASH}"
USER=`jq -r ".pusher.name" "${EVENT_PATH}"`
echo "Run for push of ${BRANCH_NAME} from ${FROM_HASH} to ${TO_HASH} on ${REPO} by ${USER}"
else
## Doesn't appear to be a PR or a push
error "Unknown Github Event Payload"
fi
## Fetch both branches for PR
if [[ "${isPR}" = true ]]; then
echo "::group::Get PR Branches"
echo "Fetch Branch Histories"
if [[ ! -z "${INPUT_FETCH_DEPTH}" ]]; then
echo "Histories to depth: ${INPUT_FETCH_DEPTH}"
git fetch origin "${PR_BRANCH}" --recurse-submodules=no --depth "${INPUT_FETCH_DEPTH}" || error "__Line:${LINENO}__Error: Could not fetch history of ${PR_BRANCH}"
git fetch origin "${BASE_BRANCH}" --recurse-submodules=no --depth "${INPUT_FETCH_DEPTH}" || error "__Line:${LINENO}__Error: Could not fetch history of ${BASE_BRANCH}"
else
echo "Full Brach Histories"
git fetch origin --recurse-submodules=no "${PR_BRANCH}" || error "__Line:${LINENO}__Error: Could not fetch history of ${PR_BRANCH}"
git fetch origin --recurse-submodules=no "${BASE_BRANCH}" || error "__Line:${LINENO}__Error: Could not fetch history of ${BASE_BRANCH}"
fi
echo "::endgroup::"
else
## Fetch last two commits for push
echo "::group::Get Branch Push History"
echo "Fetching last two commits"
git fetch origin "${BRANCH_NAME}" --recurse-submodules=no --depth 2 || error "__Line:${LINENO}__Error: Could not fetch history of ${BRANCH_NAME}"
echo "::endgroup::"
fi
echo "::endgroup::"
echo "::group::Get Submodule Info"
## Move to end hash when setting up submodule, otherwise would fail if submodule does not exist on whetever was originally checked out
git checkout "${TO_HASH}" || error "__Line:${LINENO}__Error: Could not checkout ${TO_HASH}"
## Check for submodule valid
SUBMODULES=`git config --file .gitmodules --get-regexp path | awk '{ print $2 }'`
echo "${SUBMODULES}" | grep -x "${INPUT_PATH}" || error "Error: path \"${INPUT_PATH}\" is not a submodule on ${TO_HASH}"
## Initialize Submodule
git submodule update --init --depth=1 "${INPUT_PATH}" || error "__Line:${LINENO}__Error: Could not initialize submodule ${INPUT_PATH} as referenced by ${PR_BRANCH} (is the referenced commit pushed to remote?)"
cd "${INPUT_PATH}" || error "__Line:${LINENO}__Error: Cannot change directory to the submodule"
SUBMODULE_HASH=`git rev-parse HEAD`
## Update Submodule
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
if [[ ! -z "${INPUT_SUB_FETCH_DEPTH}" ]]; then
echo "Submodule History to depth: ${INPUT_SUB_FETCH_DEPTH}"
git fetch --recurse-submodules=no --depth "${INPUT_SUB_FETCH_DEPTH}" || error "__Line:${LINENO}__Error: Error Fetching Submodule ${INPUT_PATH}"
else
echo "Full Submodule History"
if [[ "$(git rev-parse --is-shallow-repository)" = true ]]; then
git fetch --recurse-submodules=no --unshallow || error "__Line:${LINENO}__Error: Error Fetching Submodule ${INPUT_PATH}"
else
git fetch --recurse-submodules=no || error "__Line:${LINENO}__Error: Error Fetching Submodule ${INPUT_PATH}"
fi
fi
cd "${GITHUB_WORKSPACE}" || error "__Line:${LINENO}__Error: Cannot change directory to Github Workspace"
git checkout "${FROM_HASH}" || error "__Line:${LINENO}__Error: Could not checkout ${FROM_HASH}"
## Check if submodule is new between commits/branches
BASESUBMODULES=`git config --file .gitmodules --get-regexp path | awk '{ print $2 }'`
echo "${BASESUBMODULES}" | grep -x "${INPUT_PATH}" || newSubmoduleWarning "${INPUT_PATH}"
## Only get submodule on base if it exists
if [ "$newSubmodule" = false ]; then
git submodule update -N "${INPUT_PATH}" || error "__Line:${LINENO}__Error: Could not checkout submodule hash referenced by ${BASE_BRANCH}. It may not be pushed to remote or deeper than workflow shallow clone"
cd "${INPUT_PATH}" || error "__Line:${LINENO}__Error: Cannot change directory to the submodule"
SUBMODULE_HASH_BASE=`git rev-parse HEAD`
echo "Submodule ${INPUT_PATH} Changed from: ${SUBMODULE_HASH_BASE} to ${SUBMODULE_HASH}"
fi
fail () {
echo "::error file=${INPUT_PATH}::$1"
echo "fails=$1" >> $GITHUB_OUTPUT
restoreState
exit 1
}
pass () {
echo -e "\033[0;32mPASS: $1\033[0m"
echo "fails=" >> $GITHUB_OUTPUT
restoreState
exit 0
}
cd "${GITHUB_WORKSPACE}" || error "__Line:${LINENO}__Error: Cannot change directory to Github Workspace"
echo "::endgroup::"
## Immediately pass if submodule is not changed (PR only)
if [[ ! -z "${INPUT_PASS_IF_UNCHANGED}" ]]; then
echo "::group::Check if Unchanged"
if [[ "${isPR}" = true ]]; then
echo "Check if submodule has been changed on ${PR_BRANCH}"
CHANGED=`git diff --name-only ${FROM_HASH}...${TO_HASH}`
if ! grep "^${INPUT_PATH}$" <<< "${CHANGED}"; then
pass "Submodule ${INPUT_PATH} has not been changed on branch ${PR_BRANCH}"
fi
echo "Submodule has been changed"
else
echo "Note: Not a PR - Pass if Unchanged ignored"
fi
echo "::endgroup::"
fi
cd "${INPUT_PATH}" || error "__Line:${LINENO}__Error: Cannot change directory to the submodule"
## Check if most recent required
if [[ ! -z "${INPUT_REQUIRE_HEAD}" ]]; then
echo "::group::Check if Most Recent"
echo "Check if on most recent"
if [[ -z "${INPUT_BRANCH}" ]]; then
error "Error: Branch not provided but Head Commit is required"
fi
HEAD_SHA=`git rev-parse origin/${INPUT_BRANCH}`
if [ "${HEAD_SHA}" == "${SUBMODULE_HASH}" ]; then
pass "${INPUT_PATH} is the the most recent ${INPUT_BRANCH}"
else
fail "Submodule ${INPUT_PATH} is not on most recent ${INPUT_BRANCH} ($HEAD_SHA)"
fi
echo "::endgroup::"
fi
## Check if on required branch
if [[ ! -z "${INPUT_BRANCH}" ]]; then
echo "::group::Check Required Branch"
echo "Check for submodule on branch ${INPUT_BRANCH}"
BRANCHES=`git branch -r --contains ${SUBMODULE_HASH}`
echo "${BRANCHES}" | grep "/${INPUT_BRANCH}$" || fail "Submodule ${INPUT_PATH} Hash ${SUBMODULE_HASH} is not on branch ${INPUT_BRANCH}"
echo "Submodule is on branch ${INPUT_BRANCH}"
echo "::endgroup::"
if [[ ! -z "${INPUT_FIRST_PARENT}" ]]; then
echo "::group::Check First-Parent Ancestry"
git rev-list --first-parent ${INPUT_BRANCH} --not ${SUBMODULE_HASH}^@ | grep "${SUBMODULE_HASH}" || fail "Commit ${SUBMODULE_HASH} is not a first-parent ancestor of the tip of ${INPUT_BRANCH}"
echo "Commit ${SUBMODULE_HASH} is a first-parent ancestor of the tip of ${INPUT_BRANCH}"
echo "::endgroup::"
fi
fi
##only check for progression if we have something to compare against
if [[ ! -z "${INPUT_DISABLE_PROGRESSION}" ]]; then
echo "Progression Check Disabled"
elif [ "$newSubmodule" = true ]; then
echo "New Submodule, skipping progression check"
else
echo "::group::Check Progression"
## If they are the same pass
echo "Check if submodule is identical hash"
if [ "${SUBMODULE_HASH_BASE}" == "${SUBMODULE_HASH}" ]; then
pass "${INPUT_PATH} is the same as ${BASE_BRANCH}"
fi
## Check that base hash is an ancestor of the ref hash
echo "Verify old submodule hash is ancestor of current"
git rev-list "${SUBMODULE_HASH}" | grep "${SUBMODULE_HASH_BASE}" || fail "Submodule ${INPUT_PATH} on ${BASE_BRANCH} is not an ancestor of that on ${PR_BRANCH}"
echo "::endgroup::"
fi
pass "Valid submodule ${INPUT_PATH} on ${PR_BRANCH}"