-
Notifications
You must be signed in to change notification settings - Fork 36
360 lines (314 loc) · 15 KB
/
Copy pathta-tests.yml
File metadata and controls
360 lines (314 loc) · 15 KB
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
name: TAs Regression Test
on:
push:
branches:
- develop
- main
pull_request:
branches:
- "**"
workflow_dispatch:
inputs:
target_repo:
description: "TA repository (leave empty to test all TAs)"
required: false
default: ""
target_branch:
description: "TA repository branch"
required: false
default: "main"
splunktaucclib_branch:
description: "Branch of splunk/addonfactory-ucc-library to use (leave empty to use latest from PyPI)"
required: false
default: ""
run_pipelines:
description: "Trigger TA pipelines (true/false)"
required: false
default: "false"
env:
POETRY_VERSION: "2.1.4"
POETRY_EXPORT_PLUGIN_VERSION: "1.9.0"
jobs:
build-ucc:
runs-on: ubuntu-latest
steps:
- name: Checkout UCC Framework Repository
uses: actions/checkout@v7
with:
path: UCC
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.9"
- name: Install Poetry ${{env.POETRY_VERSION}}
run: curl -sSL https://install.python-poetry.org | python3 - --version ${{env.POETRY_VERSION}} && poetry self add poetry-plugin-export@${{env.POETRY_EXPORT_PLUGIN_VERSION}}
- name: Install Poetry Dependencies
working-directory: UCC
run: poetry install
- name: Build UCC Framework Package
working-directory: UCC
run: poetry build
- name: Upload UCC Artifact
uses: actions/upload-artifact@v7
with:
name: ucc-package-whl
path: UCC/dist/*.whl
determine-repos:
# This job determines the repositories to run tests on based on the event type and inputs
runs-on: ubuntu-latest
outputs:
repos: ${{ steps.set-repos.outputs.repos }}
steps:
- id: set-repos
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ github.event.inputs.target_repo }}" ]]; then
echo "repos=[\"${{ github.event.inputs.target_repo }}\"]" >> $GITHUB_OUTPUT
else
# splunk/splunk-add-on-for-cisco-asa is temporarily disabled: its
# additional_packaging.py rmdir()s default/data/spl2 after deleting a
# hardcoded file list, which fails because cisco_asa_schema_1_1.json
# (added in the TA's 6.0.1 release) isn't in that list. Re-enable
# once the TA switches to shutil.rmtree or updates the list.
echo "repos<<EOF" >> $GITHUB_OUTPUT
echo '[
"splunk/splunk-add-on-for-amazon-web-services",
"splunk/splunk-add-on-for-google-cloud-platform",
"splunk/splunk-add-on-for-google-workspace",
"splunk/splunk-add-on-for-microsoft-cloud-services",
"splunk/splunk-add-on-for-microsoft-office-365",
"splunk/splunk-add-on-for-salesforce",
"splunk/splunk-add-on-for-servicenow",
"splunk/splunk-add-on-for-mysql",
"splunk/splunk-add-on-for-unix-and-linux"
]' >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
fi
test-addons:
needs: [ build-ucc, determine-repos ]
strategy:
matrix:
target_repo: ${{ fromJSON(needs.determine-repos.outputs.repos) }}
continue-on-error: true
runs-on: ubuntu-latest
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.GH_APP_CLIENT_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout Target Add-on Repository
uses: actions/checkout@v7
with:
repository: ${{ matrix.target_repo }}
path: TA
token: ${{ steps.app-token.outputs.token }}
ref: ${{ github.event.inputs.target_branch }}
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.9"
- name: Install Poetry ${{env.POETRY_VERSION}}
run: curl -sSL https://install.python-poetry.org | python3 - --version ${{env.POETRY_VERSION}} && poetry self add poetry-plugin-export@${{env.POETRY_EXPORT_PLUGIN_VERSION}}
- name: Download UCC Artifact
uses: actions/download-artifact@v8
with:
name: ucc-package-whl
path: UCC
- name: Importing GPG key
if: success() && github.event.inputs.run_pipelines == 'true'
uses: crazy-max/ghaction-import-gpg@v7
with:
git_committer_name: ${{ secrets.SA_GH_USER_NAME }}
git_committer_email: ${{ secrets.SA_GH_USER_EMAIL }}
gpg_private_key: ${{ secrets.SA_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.SA_GPG_PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
workdir: TA
- name: Prepare the Target Add-on
id: prepare
working-directory: TA
run: |
set -x
# https://github.com/python-poetry/poetry/issues/7491#issuecomment-1423763839
git config --global --add url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com".insteadOf https://github.com
git config --global --add url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com".insteadOf ssh://git@github.com
# Use the special branch
if [[ "${{ github.event.inputs.run_pipelines }}" == "true" ]]; then
GIT_BRANCH="ucc/ci_tests_trigger_pipeline"
git fetch origin
if git ls-remote --exit-code --heads origin "$GIT_BRANCH"; then
echo "Branch $GIT_BRANCH already exists, checking it out"
git checkout "$GIT_BRANCH"
git reset --hard "origin/${{ github.event.inputs.target_branch }}" # Reset to main branch
git rebase ${{ github.event.inputs.target_branch }} $GIT_BRANCH # Rebase the branch onto main
else
echo "Branch $GIT_BRANCH does not exist, creating it"
git checkout -b "$GIT_BRANCH" "origin/${{ github.event.inputs.target_branch }}"
fi
echo "GIT_BRANCH=$GIT_BRANCH" >> "$GITHUB_ENV"
fi
rm splunk_add_on_ucc_framework-*.whl || true
cp ../UCC/*.whl ./
UCC_WHL=$(ls *.whl)
echo "UCC_WHL=$UCC_WHL" >> "$GITHUB_ENV"
echo "Adding UCC package $UCC_WHL"
# Remove existing splunk_add_on_ucc_framework if present
poetry remove splunk_add_on_ucc_framework || true
if [[ -f requirements_ucc.txt ]]; then
echo "Modifying existing requirements_ucc.txt"
cat requirements_ucc.txt | grep -v "splunk-add-on-ucc-framework" > requirements_ucc.txt.new || true
mv requirements_ucc.txt.new requirements_ucc.txt
fi
echo "./$UCC_WHL" >> requirements_ucc.txt
# Adding "package-mode = false" to pyproject.toml if not present
if ! grep -q "package-mode = false" pyproject.toml; then
echo "Adding 'package-mode = false' to pyproject.toml"
sed -i '/name = .*/ s:$:\npackage-mode = false:' pyproject.toml
fi
# Install splunktaucclib with retries
MAX_RETRIES=3
RETRY_COUNT=0
until [ $RETRY_COUNT -ge $MAX_RETRIES ]
do
if [[ -n "${{ github.event.inputs.splunktaucclib_branch }}" ]]; then
echo "Installing splunktaucclib from branch ${{ github.event.inputs.splunktaucclib_branch }}"
poetry add git+https://github.com/splunk/addonfactory-ucc-library.git@${{ github.event.inputs.splunktaucclib_branch }} && break
else
echo "Installing latest splunktaucclib from PyPI"
poetry add splunktaucclib@latest && break
fi
RETRY_COUNT=$((RETRY_COUNT+1))
if [[ $RETRY_COUNT -eq $MAX_RETRIES ]]; then
echo "splunktaucclib install failed after $MAX_RETRIES attempts, exiting"
exit 1
fi
echo "splunktaucclib install failed, retry attempt $RETRY_COUNT of $MAX_RETRIES"
sleep 5
done
mkdir -p package/lib
poetry export --without-hashes -o package/lib/requirements.txt
# Add to commit
if [[ "${{ github.event.inputs.run_pipelines }}" == "true" ]]; then
echo "Adding UCC, requirements_ucc.txt, pyproject.toml and poetry.lock to commit"
git add pyproject.toml requirements_ucc.txt poetry.lock *.whl
fi
- name: Run ucc-gen build in Target Add-on
working-directory: TA
run: |
set -x
python3 -m venv .ucc_venv
./.ucc_venv/bin/python3 -m pip install ./$UCC_WHL
./.ucc_venv/bin/ucc-gen build 2>&1 | tee build_output.log
if grep -q "^INFO: File creation summary: created: " build_output.log; then
echo "✓ Build completed successfully with expected output"
cat build_output.log
else
echo "✗ Build did not complete with expected output"
echo "Output should contain a line starting with 'INFO: File creation summary: created: '"
echo "Full output:"
cat build_output.log
exit 1
fi
- name: Upgrade the release pipeline in Github Actions
if: success() && github.event.inputs.run_pipelines == 'true'
working-directory: TA
run: |
set -x
VERSION="$(cat .github/workflows/build-test-release.yml | grep reusable-build-test-release.yml | cut -d '@' -f 2)"
# Version is in format e.g. "v1.2.3". We need at least "v5.1.0"
MAJOR_VERSION="$(echo $VERSION | cut -d '.' -f 1 | sed 's/^v//')"
MINOR_VERSION="$(echo $VERSION | cut -d '.' -f 2)"
# If major and minor are not integers, exit
if ! [[ "$MAJOR_VERSION" =~ ^[0-9]+$ ]] || ! [[ "$MINOR_VERSION" =~ ^[0-9]+$ ]]; then
echo "✗ The reusable workflow version $VERSION is not in the expected format. No update performed."
exit 0
fi
if (( MAJOR_VERSION < 5 )) || { (( MAJOR_VERSION == 5 )) && (( MINOR_VERSION < 1 )); }; then
echo "✗ The reusable workflow version $VERSION is too old. Upgrading to v5.1.0"
sed -i 's/reusable-build-test-release.yml@.*/reusable-build-test-release.yml@v5.1.0/' .github/workflows/build-test-release.yml
git add .github/workflows/build-test-release.yml
echo "Upgraded the reusable workflow version to v5.1.0"
else
echo "✓ The reusable workflow version $VERSION is up to date"
fi
- name: Push changes to a temporary branch in order to trigger the pipeline
if: success() && github.event.inputs.run_pipelines == 'true'
working-directory: TA
run: |
git config --global user.name "${{ secrets.SA_GH_USER_NAME }}"
git config --global user.email "${{ secrets.SA_GH_USER_EMAIL }}"
git commit -S -m "CI: UCC build for ${{ github.event_name }} event"
git push --force origin $GIT_BRANCH
- name: Create a PR if it does not exist yet
if: success() && github.event.inputs.run_pipelines == 'true'
working-directory: TA
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
echo "Creating a new draft PR from branch $GIT_BRANCH to ${{ github.event.inputs.target_branch }}"
gh pr create -R ${{ matrix.target_repo }} --title "CI: UCC build for ${{ github.event_name }} event" \
--body "This PR was created automatically to trigger the build-test-release pipeline." \
--base ${{ github.event.inputs.target_branch }} --head $GIT_BRANCH --draft || true
- name: Obtain the workflow run ID
if: success() && github.event.inputs.run_pipelines == 'true'
id: get-workflow-run-id
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
echo "Waiting for the workflow run to be created..."
sleep 30 # Wait for a while to ensure the workflow run is created
for i in {1..30}; do
echo "Attempt $i to get workflow run ID"
WORKFLOW_RUN_ID=$(gh run -R ${{ matrix.target_repo }} list -b ucc/ci_tests_trigger_pipeline \
--json databaseId --limit 1 --status in_progress --workflow build-test-release \
-q '.[0].databaseId | select( . != null )')
if [[ -n "$WORKFLOW_RUN_ID" ]]; then
echo "Found workflow run ID: $WORKFLOW_RUN_ID"
break
fi
echo "Workflow run ID not found, retrying in 10 seconds..."
sleep 10
done
if [[ -z "$WORKFLOW_RUN_ID" ]]; then
echo "Failed to obtain workflow run ID after multiple attempts, exiting"
exit 1
fi
echo "WORKFLOW_RUN_ID=$WORKFLOW_RUN_ID" >> $GITHUB_ENV
echo "workflow_run_id=$WORKFLOW_RUN_ID" >> $GITHUB_OUTPUT
- name: Wait for the workflow run to complete
if: success()
id: wait-for-workflow
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
if [[ -z "$WORKFLOW_RUN_ID" ]]; then
echo "No workflow run ID found, skipping wait"
exit 0
fi
WORKFLOW_URL="https://github.com/${{ matrix.target_repo }}/actions/runs/$WORKFLOW_RUN_ID"
echo "Workflow URL: $WORKFLOW_URL"
echo "Workflow run ID: $WORKFLOW_RUN_ID"
echo "Waiting for workflow run $WORKFLOW_RUN_ID to start..."
sleep 300 # Initial wait to allow the workflow to start properly
echo "Waiting for workflow run $WORKFLOW_RUN_ID to complete..."
gh run watch -R ${{ matrix.target_repo }} "$WORKFLOW_RUN_ID" -i 120 2>&1 | tee watch_output.log
RESULTS_JSON="$(gh run view -R ${{ matrix.target_repo }} "$WORKFLOW_RUN_ID" --json jobs)"
echo "Checking results of not-skipped jobs 'build' and 'spl2'"
RESULTS="$(echo $RESULTS_JSON | jq -r '.jobs[] | select(.conclusion != "skipped")
| select(.name | test("build|spl2"))
| "\(.name): \(.conclusion)"')"
[[ $(printf '%s\n' "$RESULTS" | cut -d ':' -f 2 | cut -d ' ' -f 2 | sort | uniq) == "success" ]] && exit 0
echo "One or more jobs failed. Details:"
echo "$WORKFLOW_URL"
exit 1
- name: Cleanup temporary branch
if: always() && github.event.inputs.run_pipelines == 'true'
working-directory: TA
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
echo "Deleting temporary branch $GIT_BRANCH"
gh api -X DELETE repos/${{ matrix.target_repo }}/git/refs/heads/$GIT_BRANCH || true