-
Notifications
You must be signed in to change notification settings - Fork 15
236 lines (194 loc) · 9.11 KB
/
integrate.yml
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
232
233
234
235
236
name: Integration
on:
workflow_dispatch:
inputs:
reflector_access_token:
description: Access token for use in authenticating as the Reflector bot
type: string
reflector_user_id:
description: User id of the Reflector bot
type: string
permissions:
contents: write
pull-requests: write
# This is a workaround for the GitHub cli requiring excessive permissions when updating a pull
# request (https://github.com/cli/cli/discussions/5307)
repository-projects: read
jobs:
generate-update:
concurrency:
group: integration
cancel-in-progress: true
runs-on: ubuntu-22.04
env:
INT_BRANCH: integration
TARGET_BRANCH: main
steps:
# Checkout both the target and integration branches
- uses: actions/[email protected]
with:
token: ${{ inputs.reflector_access_token }}
fetch-depth: 0
# Attempt to merge target branch in to integration branch. Discarding any generated code on
# the integration branch
- name: Merge target
run: |
git config --local user.name "oxide-reflector-bot[bot]"
git config --local user.email "${{ inputs.reflector_user_id }}+oxide-reflector-bot[bot]@users.noreply.github.com"
MERGE_STATUS=0
git checkout $INT_BRANCH 2>/dev/null || git checkout -b $INT_BRANCH
git merge $TARGET_BRANCH || MERGE_STATUS=$?
# If there was a merge conflict attempt to reset the generated files and commit them back
if [ $MERGE_STATUS -eq 1 ]
then
echo "Found conflicts. Attempt to use changes from $TARGET_BRANCH"
# Reset generated files
git checkout $TARGET_BRANCH -- cli/docs/cli.json
git checkout $TARGET_BRANCH -- cli/src/generated_cli.rs
git checkout $TARGET_BRANCH -- sdk/src/generated_sdk.rs
git checkout $TARGET_BRANCH -- sdk-httpmock/src/generated_httpmock.rs
# Always reset the Cargo.lock. It will be updated later
git checkout $TARGET_BRANCH -- Cargo.lock
# Commit the merge
git commit -m "Merge branch '$TARGET_BRANCH' into $INT_BRANCH and reset generated code"
fi
# Ensure there are no outstanding conflicts
STATUS=$(git status --porcelain=v1 2>/dev/null | wc -l)
if [ $STATUS -eq 0 ]
then
exit 0
else
echo 'Found additional conflicts from merge attempt that need to be manually resolved'
git status
exit 1
fi
# Configure Rust tools
- name: Install nightly rustfmt
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: rustfmt
default: false
- name: Report cargo version
run: cargo --version
- name: Report rustfmt version
run: cargo fmt -- --version
- name: Update progenitor
run: |
# Capture the progenitor commit from the target branch
git checkout $TARGET_BRANCH
FROM=$(cargo tree -i progenitor | grep -Eo '#([0-9a-z]+)')
# Perform the update and capture the new commit on the integration branch
git checkout $INT_BRANCH
cargo update -p progenitor
cargo update -p progenitor-client
TO=$(cargo tree -i progenitor | grep -Eo '#([0-9a-z]+)')
echo "from=${FROM:1}" >> $GITHUB_OUTPUT
echo "to=${TO:1}" >> $GITHUB_OUTPUT
id: progenitor_versions
- name: Update schema
run: |
curl -s https://raw.githubusercontent.com/oxidecomputer/omicron/main/openapi/nexus.json --output oxide.json
SHA=$(curl -s "https://api.github.com/repos/oxidecomputer/omicron/commits?path=openapi/nexus.json&per_page=1" | jq -r '.[].sha')
echo "full=${SHA}" >> $GITHUB_OUTPUT
echo "short=${SHA:0:8}" >> $GITHUB_OUTPUT
id: schema_sha
- name: Rebuild client
run: |
cargo run -p xtask generate
# Tests are allowed to fail so that a partial PR can at least be generated. This is likely to
# occur when updating the oxide.json schema file and new types that are not yet handled by
# the CLI are introduced. The result of this should be a PR that has the updated schema and
# corresponding generated code that will fail due to compilation errors during test.
- name: Generate docs
continue-on-error: true
run: |
EXPECTORATE=overwrite cargo test
- name: Report changes
run: git status
- name: Commit changes
run: |
git config --local user.name "oxide-reflector-bot[bot]"
git config --local user.email "${{ inputs.reflector_user_id }}+oxide-reflector-bot[bot]@users.noreply.github.com"
git add .
git commit -m "Rebuilt with latest dependency updates" || echo "Nothing to commit"
git push origin $INT_BRANCH
# Detect changes to report back
# Check if the spec file has been updated
git diff $TARGET_BRANCH...$INT_BRANCH --quiet oxide.json || specUpdate=$?
echo "spec=${specUpdate}" >> $GITHUB_OUTPUT
# Check if the generated docs spec file has been updated
git diff $TARGET_BRANCH...$INT_BRANCH --quiet cli/docs/cli.json || docsUpdate=$?
echo "docs=${docsUpdate}" >> $GITHUB_OUTPUT
# Check if anything in the lock file has updated
git diff $TARGET_BRANCH...$INT_BRANCH --quiet Cargo.lock || depsUpdate=$?
echo "deps=${depsUpdate}" >> $GITHUB_OUTPUT
id: committed
- name: Update pull request
env:
GH_TOKEN: ${{ inputs.reflector_access_token }}
run: |
# Compare the integration branch with the target branch
CHANGED_FILES=$(git diff integration..main --name-only | wc -l)
TARGET_TO_INT="$(git rev-list --count $TARGET_BRANCH..$INT_BRANCH)"
INT_TO_TARGET="$(git rev-list --count $INT_BRANCH..$TARGET_BRANCH)"
# Check for an existing pull request from the integration branch to the target branch
eval $(gh pr view $INT_BRANCH --repo $GITHUB_REPOSITORY --json url,number,state | jq -r 'to_entries[] | "\(.key | ascii_upcase)=\(.value)"')
HASPR=0
[ "$NUMBER" != "" ] && [ "$BASEREFNAME" == "$TARGET_BRANCH" ] || HASPR=$?
# When detecting if a PR is needed (or can be closed) we do not actually care about the
# distance between the branches. We care about if there are meaningful changes
if [ "$CHANGED_FILES" -eq 0 ]
then
echo "$TARGET_BRANCH is up to date with $INT_BRANCH. No pull request needed"
if [ "$HASPR" -eq 0 -a "$NUMBER" != "" ]
then
echo "Closing existing PR"
gh pr close $NUMBER
fi
elif [ "$TARGET_TO_INT" -gt 0 ]
then
echo "$TARGET_BRANCH is behind $INT_BRANCH ($TARGET_TO_INT)"
title=""
echo "" > body
if [ ${{ steps.committed.outputs.deps }} ]
then
title+=" dependencies"
echo "Lock file updated" >> body
echo "" >> body
fi
if [ "${{ steps.progenitor_versions.outputs.from }}" != "${{ steps.progenitor_versions.outputs.to }}" ]
then
if [ title != "" ]; then title+=","; fi
title+=" progenitor to ${{ steps.progenitor_versions.outputs.to }}"
progenitorDiffUrl="https://github.com/oxidecomputer/progenitor/compare/${{ steps.progenitor_versions.outputs.from }}...${{ steps.progenitor_versions.outputs.to }}"
echo "Bump [progenitor](https://github.com/oxidecomputer/progenitor) from \`${{ steps.progenitor_versions.outputs.from }}\` to \`${{ steps.progenitor_versions.outputs.to }}\`" >> body
echo "Changes: ${progenitorDiffUrl}" >> body
echo "" >> body
fi
if [ ${{ steps.committed.outputs.spec }} ]
then
if [ title != "" ]; then title+=","; fi
title+=" oxide.json to omicron:${{ steps.schema_sha.outputs.short }}"
schemaLabel="nexus.json \`${{ steps.schema_sha.outputs.short }}\`"
schemaUrl="https://github.com/oxidecomputer/omicron/blob/${{ steps.schema_sha.outputs.full }}/openapi/nexus.json"
echo "Generated code against [$schemaLabel]($schemaUrl)" >> body
echo "" >> body
fi
if [ ${{ steps.committed.outputs.docs }} ]
then
echo "CLI docs updated against the updated CLI" >> body
echo "" >> body
fi
title="Bump${title}"
if [ -z "$NUMBER" -o "$STATE" != "OPEN" ]
then
gh pr create -B $TARGET_BRANCH -H $INT_BRANCH --title "$title" --body-file body
else
echo "PR already exists: ($NUMBER) $URL . Updating..."
gh pr edit "$NUMBER" --title "$title" --body-file body
fi
else
echo "$INT_BRANCH is behind $TARGET_BRANCH ($INT_TO_TARGET). This is likely an error"
exit 1
fi