switchroom 0.13.2 → 0.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-scheduler/index.js +2 -2
- package/dist/auth-broker/index.js +2 -2
- package/dist/cli/switchroom.js +132 -214
- package/dist/host-control/main.js +2 -2
- package/dist/vault/approvals/kernel-server.js +2 -2
- package/dist/vault/broker/server.js +2 -2
- package/package.json +1 -1
- package/profiles/_base/start.sh.hbs +8 -8
- package/profiles/default/CLAUDE.md.hbs +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +42 -10
- package/telegram-plugin/gateway/boot-probes.ts +13 -6
- package/telegram-plugin/gateway/gateway.ts +44 -6
- package/telegram-plugin/hooks/silent-end-interrupt-stop.mjs +5 -1
- package/telegram-plugin/silent-end.ts +56 -0
- package/telegram-plugin/tests/boot-probes.test.ts +26 -2
- package/telegram-plugin/tests/silent-end.test.ts +69 -0
- package/telegram-plugin/uat/scenarios/bridge-flap-resilience-dm.test.ts +166 -0
- package/skills/buildkite-agent-infrastructure/SKILL.md +0 -321
- package/skills/buildkite-agent-infrastructure/agents/openai.yaml +0 -6
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-infrastructure/references/audit-logging.md +0 -87
- package/skills/buildkite-agent-infrastructure/references/graphql-mutations.md +0 -690
- package/skills/buildkite-agent-infrastructure/references/instance-shapes.md +0 -38
- package/skills/buildkite-agent-infrastructure/references/pipeline-templates.md +0 -73
- package/skills/buildkite-agent-infrastructure/references/self-hosted-agents.md +0 -137
- package/skills/buildkite-agent-infrastructure/references/sso-saml.md +0 -92
- package/skills/buildkite-agent-runtime/SKILL.md +0 -509
- package/skills/buildkite-agent-runtime/agents/openai.yaml +0 -6
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-runtime/references/flag-reference.md +0 -417
- package/skills/buildkite-agent-runtime/references/patterns-and-recipes.md +0 -555
- package/skills/buildkite-api/SKILL.md +0 -308
- package/skills/buildkite-api/agents/openai.yaml +0 -6
- package/skills/buildkite-api/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-api/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-api/references/graphql-reference.md +0 -195
- package/skills/buildkite-api/references/patterns.md +0 -44
- package/skills/buildkite-api/references/webhooks.md +0 -161
- package/skills/buildkite-cli/SKILL.md +0 -397
- package/skills/buildkite-cli/agents/openai.yaml +0 -6
- package/skills/buildkite-cli/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-cli/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-cli/references/command-reference.md +0 -181
- package/skills/buildkite-migration/SKILL.md +0 -195
- package/skills/buildkite-pipelines/SKILL.md +0 -481
- package/skills/buildkite-pipelines/agents/openai.yaml +0 -6
- package/skills/buildkite-pipelines/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-pipelines/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-pipelines/examples/basic-pipeline.yml +0 -24
- package/skills/buildkite-pipelines/examples/optimized-pipeline.yml +0 -100
- package/skills/buildkite-pipelines/references/advanced-patterns.md +0 -286
- package/skills/buildkite-pipelines/references/retry-and-error-codes.md +0 -131
- package/skills/buildkite-pipelines/references/step-types-reference.md +0 -225
- package/skills/buildkite-secure-delivery/SKILL.md +0 -182
- package/skills/buildkite-secure-delivery/agents/openai.yaml +0 -6
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-secure-delivery/references/oidc-cloud-providers.md +0 -83
- package/skills/buildkite-secure-delivery/references/package-publishing.md +0 -100
- package/skills/buildkite-test-engine/SKILL.md +0 -256
- package/skills/buildkite-test-engine/agents/openai.yaml +0 -6
- package/skills/buildkite-test-engine/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-test-engine/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-test-engine/examples/bktec-splitting.yml +0 -16
- package/skills/buildkite-test-engine/examples/collector-pipeline.yml +0 -11
- package/skills/buildkite-test-engine/references/collectors.md +0 -198
- package/skills/buildkite-test-engine/references/splitting-examples.md +0 -93
|
@@ -1,555 +0,0 @@
|
|
|
1
|
-
# Patterns and Recipes
|
|
2
|
-
|
|
3
|
-
Advanced usage patterns combining multiple `buildkite-agent` runtime subcommands. Each recipe shows a real-world scenario with complete, copy-pasteable code.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Test failure annotation with artifact links
|
|
8
|
-
|
|
9
|
-
Annotate the build page with a formatted test failure summary and link to the uploaded report.
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
#!/bin/bash
|
|
13
|
-
set -euo pipefail
|
|
14
|
-
|
|
15
|
-
# Run tests and capture output
|
|
16
|
-
if ! make test 2>&1 | tee test-output.txt; then
|
|
17
|
-
# Upload the full test output as an artifact
|
|
18
|
-
buildkite-agent artifact upload "test-output.txt"
|
|
19
|
-
|
|
20
|
-
# Count failures for the summary
|
|
21
|
-
FAIL_COUNT=$(grep -c "FAIL" test-output.txt || true)
|
|
22
|
-
|
|
23
|
-
# Create a rich annotation with failure details and artifact link
|
|
24
|
-
buildkite-agent annotate --style "error" --context "test-failures" <<EOF
|
|
25
|
-
## :x: ${FAIL_COUNT} test(s) failed
|
|
26
|
-
|
|
27
|
-
<details>
|
|
28
|
-
<summary>Failure summary (click to expand)</summary>
|
|
29
|
-
|
|
30
|
-
\`\`\`
|
|
31
|
-
$(grep -A 3 "FAIL" test-output.txt | head -50)
|
|
32
|
-
\`\`\`
|
|
33
|
-
|
|
34
|
-
</details>
|
|
35
|
-
|
|
36
|
-
Full output: <a href="artifact://test-output.txt">test-output.txt</a>
|
|
37
|
-
EOF
|
|
38
|
-
exit 1
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
# Success annotation
|
|
42
|
-
buildkite-agent annotate ":white_check_mark: All tests passed" \
|
|
43
|
-
--style "success" --context "test-failures"
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Pipeline YAML:**
|
|
47
|
-
|
|
48
|
-
```yaml
|
|
49
|
-
steps:
|
|
50
|
-
- label: ":test_tube: Tests"
|
|
51
|
-
command: ".buildkite/scripts/test-with-annotations.sh"
|
|
52
|
-
artifact_paths: "test-output.txt"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Progressive annotation with parallel jobs
|
|
58
|
-
|
|
59
|
-
Each parallel job appends its results to a shared annotation. The final step summarizes.
|
|
60
|
-
|
|
61
|
-
```yaml
|
|
62
|
-
steps:
|
|
63
|
-
- label: ":rspec: Tests %n"
|
|
64
|
-
command: ".buildkite/scripts/test-parallel.sh"
|
|
65
|
-
parallelism: 4
|
|
66
|
-
|
|
67
|
-
- wait: ~
|
|
68
|
-
continue_on_failure: true
|
|
69
|
-
|
|
70
|
-
- label: ":bar_chart: Summary"
|
|
71
|
-
command: ".buildkite/scripts/test-summary.sh"
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
**test-parallel.sh:**
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
#!/bin/bash
|
|
78
|
-
set -euo pipefail
|
|
79
|
-
|
|
80
|
-
JOB_INDEX="${BUILDKITE_PARALLEL_JOB}"
|
|
81
|
-
TOTAL="${BUILDKITE_PARALLEL_JOB_COUNT}"
|
|
82
|
-
|
|
83
|
-
# Run this job's slice of the test suite
|
|
84
|
-
bundle exec rspec $(./scripts/split-tests.sh "$JOB_INDEX" "$TOTAL") \
|
|
85
|
-
--format json --out "results-${JOB_INDEX}.json" \
|
|
86
|
-
--format progress || true
|
|
87
|
-
|
|
88
|
-
# Upload results as artifact
|
|
89
|
-
buildkite-agent artifact upload "results-${JOB_INDEX}.json"
|
|
90
|
-
|
|
91
|
-
# Store pass/fail in meta-data
|
|
92
|
-
if jq -e '.summary.failure_count == 0' "results-${JOB_INDEX}.json" > /dev/null; then
|
|
93
|
-
buildkite-agent meta-data set "test-result-${JOB_INDEX}" "passed"
|
|
94
|
-
else
|
|
95
|
-
FAILURES=$(jq '.summary.failure_count' "results-${JOB_INDEX}.json")
|
|
96
|
-
buildkite-agent meta-data set "test-result-${JOB_INDEX}" "failed:${FAILURES}"
|
|
97
|
-
fi
|
|
98
|
-
|
|
99
|
-
# Append this job's result to the shared annotation
|
|
100
|
-
buildkite-agent annotate --style "info" --context "test-progress" --append <<EOF
|
|
101
|
-
- Job ${JOB_INDEX}/$((TOTAL - 1)): $(buildkite-agent meta-data get "test-result-${JOB_INDEX}")
|
|
102
|
-
EOF
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
**test-summary.sh:**
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
#!/bin/bash
|
|
109
|
-
set -euo pipefail
|
|
110
|
-
|
|
111
|
-
TOTAL="${BUILDKITE_PARALLEL_JOB_COUNT:-4}"
|
|
112
|
-
PASSED=0
|
|
113
|
-
FAILED=0
|
|
114
|
-
FAILURE_DETAILS=""
|
|
115
|
-
|
|
116
|
-
for i in $(seq 0 $((TOTAL - 1))); do
|
|
117
|
-
RESULT=$(buildkite-agent meta-data get "test-result-${i}")
|
|
118
|
-
if [[ "$RESULT" == "passed" ]]; then
|
|
119
|
-
((PASSED++))
|
|
120
|
-
else
|
|
121
|
-
((FAILED++))
|
|
122
|
-
COUNT="${RESULT#failed:}"
|
|
123
|
-
FAILURE_DETAILS="${FAILURE_DETAILS}\n- Job ${i}: ${COUNT} failures"
|
|
124
|
-
fi
|
|
125
|
-
done
|
|
126
|
-
|
|
127
|
-
if [[ "$FAILED" -eq 0 ]]; then
|
|
128
|
-
buildkite-agent annotate --style "success" --context "test-summary" <<EOF
|
|
129
|
-
## :white_check_mark: All ${PASSED} test jobs passed
|
|
130
|
-
EOF
|
|
131
|
-
else
|
|
132
|
-
buildkite-agent annotate --style "error" --context "test-summary" <<EOF
|
|
133
|
-
## :x: ${FAILED}/${TOTAL} test jobs had failures
|
|
134
|
-
${FAILURE_DETAILS}
|
|
135
|
-
EOF
|
|
136
|
-
exit 1
|
|
137
|
-
fi
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## Cross-job state machine with meta-data and pipeline upload
|
|
143
|
-
|
|
144
|
-
A build where early steps determine what runs later by setting meta-data and dynamically uploading pipelines.
|
|
145
|
-
|
|
146
|
-
```yaml
|
|
147
|
-
steps:
|
|
148
|
-
- label: ":mag: Analyze"
|
|
149
|
-
command: ".buildkite/scripts/analyze.sh"
|
|
150
|
-
|
|
151
|
-
- wait
|
|
152
|
-
|
|
153
|
-
- label: ":pipeline: Plan"
|
|
154
|
-
command: ".buildkite/scripts/plan.sh"
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
**analyze.sh:**
|
|
158
|
-
|
|
159
|
-
```bash
|
|
160
|
-
#!/bin/bash
|
|
161
|
-
set -euo pipefail
|
|
162
|
-
|
|
163
|
-
# Detect what changed
|
|
164
|
-
CHANGED=$(git diff --name-only HEAD~1)
|
|
165
|
-
|
|
166
|
-
# Classify changes and store as meta-data
|
|
167
|
-
if echo "$CHANGED" | grep -q "^src/"; then
|
|
168
|
-
buildkite-agent meta-data set "needs-build" "true"
|
|
169
|
-
else
|
|
170
|
-
buildkite-agent meta-data set "needs-build" "false"
|
|
171
|
-
fi
|
|
172
|
-
|
|
173
|
-
if echo "$CHANGED" | grep -q "^test/\|^spec/"; then
|
|
174
|
-
buildkite-agent meta-data set "needs-test" "true"
|
|
175
|
-
else
|
|
176
|
-
buildkite-agent meta-data set "needs-test" "false"
|
|
177
|
-
fi
|
|
178
|
-
|
|
179
|
-
if echo "$CHANGED" | grep -qE "^(Dockerfile|docker-compose)"; then
|
|
180
|
-
buildkite-agent meta-data set "needs-docker" "true"
|
|
181
|
-
else
|
|
182
|
-
buildkite-agent meta-data set "needs-docker" "false"
|
|
183
|
-
fi
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
**plan.sh:**
|
|
187
|
-
|
|
188
|
-
```bash
|
|
189
|
-
#!/bin/bash
|
|
190
|
-
set -euo pipefail
|
|
191
|
-
|
|
192
|
-
NEEDS_BUILD=$(buildkite-agent meta-data get "needs-build")
|
|
193
|
-
NEEDS_TEST=$(buildkite-agent meta-data get "needs-test")
|
|
194
|
-
NEEDS_DOCKER=$(buildkite-agent meta-data get "needs-docker")
|
|
195
|
-
|
|
196
|
-
# Build pipeline YAML based on analysis results
|
|
197
|
-
PIPELINE="steps:"
|
|
198
|
-
|
|
199
|
-
if [[ "$NEEDS_BUILD" == "true" ]]; then
|
|
200
|
-
PIPELINE="${PIPELINE}
|
|
201
|
-
- label: ':hammer: Build'
|
|
202
|
-
key: 'build'
|
|
203
|
-
command: 'make build'"
|
|
204
|
-
fi
|
|
205
|
-
|
|
206
|
-
if [[ "$NEEDS_TEST" == "true" ]]; then
|
|
207
|
-
PIPELINE="${PIPELINE}
|
|
208
|
-
- label: ':test_tube: Test'
|
|
209
|
-
key: 'test'
|
|
210
|
-
command: 'make test'
|
|
211
|
-
depends_on: 'build'"
|
|
212
|
-
fi
|
|
213
|
-
|
|
214
|
-
if [[ "$NEEDS_DOCKER" == "true" ]]; then
|
|
215
|
-
PIPELINE="${PIPELINE}
|
|
216
|
-
- label: ':docker: Docker Build'
|
|
217
|
-
key: 'docker'
|
|
218
|
-
command: 'make docker-build'
|
|
219
|
-
depends_on: 'build'"
|
|
220
|
-
fi
|
|
221
|
-
|
|
222
|
-
# If nothing changed that we care about, skip
|
|
223
|
-
if [[ "$PIPELINE" == "steps:" ]]; then
|
|
224
|
-
PIPELINE="steps:
|
|
225
|
-
- label: ':white_check_mark: Nothing to do'
|
|
226
|
-
command: 'echo No relevant changes detected'"
|
|
227
|
-
fi
|
|
228
|
-
|
|
229
|
-
echo "$PIPELINE" | buildkite-agent pipeline upload
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
## Block step to meta-data to trigger
|
|
235
|
-
|
|
236
|
-
Collect user input via a block step, read the values from meta-data, and trigger a downstream pipeline.
|
|
237
|
-
|
|
238
|
-
```yaml
|
|
239
|
-
steps:
|
|
240
|
-
- block: ":rocket: Deploy"
|
|
241
|
-
prompt: "Choose deploy target"
|
|
242
|
-
fields:
|
|
243
|
-
- key: "deploy-env"
|
|
244
|
-
text: "Environment"
|
|
245
|
-
default: "staging"
|
|
246
|
-
hint: "staging or production"
|
|
247
|
-
- key: "deploy-version"
|
|
248
|
-
text: "Version tag"
|
|
249
|
-
required: true
|
|
250
|
-
|
|
251
|
-
- label: ":pipeline: Trigger deploy"
|
|
252
|
-
command: ".buildkite/scripts/trigger-deploy.sh"
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
**trigger-deploy.sh:**
|
|
256
|
-
|
|
257
|
-
```bash
|
|
258
|
-
#!/bin/bash
|
|
259
|
-
set -euo pipefail
|
|
260
|
-
|
|
261
|
-
# Block step field values are stored as meta-data automatically
|
|
262
|
-
ENV=$(buildkite-agent meta-data get "deploy-env")
|
|
263
|
-
VERSION=$(buildkite-agent meta-data get "deploy-version")
|
|
264
|
-
|
|
265
|
-
buildkite-agent annotate "Deploying **${VERSION}** to **${ENV}**" \
|
|
266
|
-
--style "info" --context "deploy-trigger"
|
|
267
|
-
|
|
268
|
-
buildkite-agent pipeline upload <<YAML
|
|
269
|
-
steps:
|
|
270
|
-
- trigger: "deploy-service"
|
|
271
|
-
label: ":rocket: Deploy ${VERSION} to ${ENV}"
|
|
272
|
-
build:
|
|
273
|
-
branch: "${BUILDKITE_BRANCH}"
|
|
274
|
-
message: "Deploy ${VERSION} to ${ENV}"
|
|
275
|
-
meta_data:
|
|
276
|
-
deploy-env: "${ENV}"
|
|
277
|
-
deploy-version: "${VERSION}"
|
|
278
|
-
YAML
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
---
|
|
282
|
-
|
|
283
|
-
## OIDC-authenticated Docker push with secret redaction
|
|
284
|
-
|
|
285
|
-
Authenticate to a registry using OIDC, build and push an image, then annotate the build with the image tag.
|
|
286
|
-
|
|
287
|
-
```bash
|
|
288
|
-
#!/bin/bash
|
|
289
|
-
set -euo pipefail
|
|
290
|
-
|
|
291
|
-
REGISTRY="packages.buildkite.com/my-org/my-registry"
|
|
292
|
-
IMAGE_TAG="${REGISTRY}/myapp:${BUILDKITE_BUILD_NUMBER}"
|
|
293
|
-
|
|
294
|
-
# Request OIDC token and authenticate with the registry
|
|
295
|
-
buildkite-agent oidc request-token \
|
|
296
|
-
--audience "https://${REGISTRY}" \
|
|
297
|
-
--lifetime 300 \
|
|
298
|
-
| docker login "${REGISTRY}" -u buildkite --password-stdin
|
|
299
|
-
|
|
300
|
-
# Build and push
|
|
301
|
-
docker build -t "${IMAGE_TAG}" .
|
|
302
|
-
docker push "${IMAGE_TAG}"
|
|
303
|
-
|
|
304
|
-
# Store the image tag for downstream jobs
|
|
305
|
-
buildkite-agent meta-data set "image-tag" "${IMAGE_TAG}"
|
|
306
|
-
|
|
307
|
-
# Annotate with the published image
|
|
308
|
-
buildkite-agent annotate --style "success" --context "docker-push" <<EOF
|
|
309
|
-
:docker: Published \`${IMAGE_TAG}\`
|
|
310
|
-
EOF
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
---
|
|
314
|
-
|
|
315
|
-
## OIDC with AWS role assumption
|
|
316
|
-
|
|
317
|
-
Request an OIDC token, exchange it for AWS credentials using STS, and redact the temporary credentials.
|
|
318
|
-
|
|
319
|
-
```bash
|
|
320
|
-
#!/bin/bash
|
|
321
|
-
set -euo pipefail
|
|
322
|
-
|
|
323
|
-
# Request OIDC token with AWS session tags
|
|
324
|
-
OIDC_TOKEN=$(buildkite-agent oidc request-token \
|
|
325
|
-
--audience "sts.amazonaws.com" \
|
|
326
|
-
--lifetime 300 \
|
|
327
|
-
--aws-session-tag "organization_slug,pipeline_slug")
|
|
328
|
-
|
|
329
|
-
# Exchange for AWS credentials
|
|
330
|
-
AWS_CREDS=$(aws sts assume-role-with-web-identity \
|
|
331
|
-
--role-arn "arn:aws:iam::123456789012:role/buildkite-deploy" \
|
|
332
|
-
--role-session-name "buildkite-${BUILDKITE_BUILD_NUMBER}" \
|
|
333
|
-
--web-identity-token "$OIDC_TOKEN" \
|
|
334
|
-
--output json)
|
|
335
|
-
|
|
336
|
-
# Extract and redact credentials
|
|
337
|
-
export AWS_ACCESS_KEY_ID=$(echo "$AWS_CREDS" | jq -r '.Credentials.AccessKeyId')
|
|
338
|
-
export AWS_SECRET_ACCESS_KEY=$(echo "$AWS_CREDS" | jq -r '.Credentials.SecretAccessKey')
|
|
339
|
-
export AWS_SESSION_TOKEN=$(echo "$AWS_CREDS" | jq -r '.Credentials.SessionToken')
|
|
340
|
-
|
|
341
|
-
echo "$AWS_SECRET_ACCESS_KEY" | buildkite-agent redactor add
|
|
342
|
-
echo "$AWS_SESSION_TOKEN" | buildkite-agent redactor add
|
|
343
|
-
|
|
344
|
-
# Now use AWS commands — credentials are redacted in logs
|
|
345
|
-
aws s3 cp build/app.tar.gz s3://deploy-bucket/releases/
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
|
|
350
|
-
## Parallel job coordination with locks
|
|
351
|
-
|
|
352
|
-
Multiple parallel jobs share a database, but only one should run migrations. Use `lock do/done` to ensure exactly-once execution.
|
|
353
|
-
|
|
354
|
-
```bash
|
|
355
|
-
#!/bin/bash
|
|
356
|
-
set -euo pipefail
|
|
357
|
-
|
|
358
|
-
# One-time database migration across parallel test jobs
|
|
359
|
-
echo "+++ Database setup"
|
|
360
|
-
if [[ $(buildkite-agent lock do "db-migrate") == "do" ]]; then
|
|
361
|
-
echo "Running database migrations..."
|
|
362
|
-
bundle exec rails db:migrate
|
|
363
|
-
buildkite-agent meta-data set "db-ready" "true"
|
|
364
|
-
buildkite-agent lock done "db-migrate"
|
|
365
|
-
else
|
|
366
|
-
echo "Migrations already run by another job, waiting for completion..."
|
|
367
|
-
# Poll until the migrating job marks the DB as ready
|
|
368
|
-
while ! buildkite-agent meta-data exists "db-ready" 2>/dev/null; do
|
|
369
|
-
sleep 2
|
|
370
|
-
done
|
|
371
|
-
fi
|
|
372
|
-
|
|
373
|
-
echo "+++ Running tests"
|
|
374
|
-
bundle exec rspec $(./scripts/split-tests.sh "$BUILDKITE_PARALLEL_JOB" "$BUILDKITE_PARALLEL_JOB_COUNT")
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
---
|
|
378
|
-
|
|
379
|
-
## Exclusive deploy with acquire/release locks
|
|
380
|
-
|
|
381
|
-
Only one deploy runs at a time across parallel jobs, with guaranteed lock release via trap.
|
|
382
|
-
|
|
383
|
-
```bash
|
|
384
|
-
#!/bin/bash
|
|
385
|
-
set -euo pipefail
|
|
386
|
-
|
|
387
|
-
echo "+++ Acquiring deploy lock"
|
|
388
|
-
TOKEN=$(buildkite-agent lock acquire "deploy-production")
|
|
389
|
-
trap 'buildkite-agent lock release "deploy-production" "${TOKEN}"' EXIT
|
|
390
|
-
|
|
391
|
-
echo "+++ Deploying"
|
|
392
|
-
buildkite-agent step update "label" ":rocket: Deploying to production..."
|
|
393
|
-
|
|
394
|
-
./scripts/deploy.sh
|
|
395
|
-
|
|
396
|
-
buildkite-agent step update "label" ":white_check_mark: Deployed to production"
|
|
397
|
-
buildkite-agent annotate "Deployed at $(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
398
|
-
--style "success" --context "deploy"
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
---
|
|
402
|
-
|
|
403
|
-
## Environment debugging in hooks
|
|
404
|
-
|
|
405
|
-
Debug what lifecycle hooks are doing to the environment by dumping state at each stage.
|
|
406
|
-
|
|
407
|
-
**environment hook** (`.buildkite/hooks/environment`):
|
|
408
|
-
|
|
409
|
-
```bash
|
|
410
|
-
#!/bin/bash
|
|
411
|
-
|
|
412
|
-
# Set up shared variables
|
|
413
|
-
export APP_ENV="test"
|
|
414
|
-
export DATABASE_URL="postgres://localhost:5432/test"
|
|
415
|
-
|
|
416
|
-
# Dump environment state after this hook
|
|
417
|
-
if [[ "${BUILDKITE_AGENT_DEBUG:-}" == "true" ]]; then
|
|
418
|
-
buildkite-agent env dump > /tmp/env-after-environment.json
|
|
419
|
-
fi
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
**pre-command hook** (`.buildkite/hooks/pre-command`):
|
|
423
|
-
|
|
424
|
-
```bash
|
|
425
|
-
#!/bin/bash
|
|
426
|
-
|
|
427
|
-
# Inject secrets
|
|
428
|
-
export SECRET_KEY=$(buildkite-agent secret get "SECRET_KEY")
|
|
429
|
-
|
|
430
|
-
if [[ "${BUILDKITE_AGENT_DEBUG:-}" == "true" ]]; then
|
|
431
|
-
buildkite-agent env dump > /tmp/env-after-pre-command.json
|
|
432
|
-
|
|
433
|
-
# Compare with environment hook (keys only — don't log values)
|
|
434
|
-
echo "New vars added by pre-command hook:"
|
|
435
|
-
diff <(jq -r 'keys[]' /tmp/env-after-environment.json) \
|
|
436
|
-
<(jq -r 'keys[]' /tmp/env-after-pre-command.json) \
|
|
437
|
-
| grep "^>" || echo "(none)"
|
|
438
|
-
fi
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
---
|
|
442
|
-
|
|
443
|
-
## Dynamic annotation dashboard
|
|
444
|
-
|
|
445
|
-
Build a live-updating dashboard annotation that multiple steps contribute to throughout a build.
|
|
446
|
-
|
|
447
|
-
```bash
|
|
448
|
-
# Step 1: Initialize the dashboard
|
|
449
|
-
buildkite-agent annotate --style "info" --context "dashboard" <<'EOF'
|
|
450
|
-
## Build Dashboard
|
|
451
|
-
| Stage | Status | Duration |
|
|
452
|
-
|-------|--------|----------|
|
|
453
|
-
EOF
|
|
454
|
-
|
|
455
|
-
# Helper function (include in each step that updates the dashboard)
|
|
456
|
-
update_dashboard() {
|
|
457
|
-
local stage="$1" status="$2" duration="$3"
|
|
458
|
-
buildkite-agent annotate --style "info" --context "dashboard" --append <<EOF
|
|
459
|
-
| ${stage} | ${status} | ${duration} |
|
|
460
|
-
EOF
|
|
461
|
-
}
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
**Usage in each step:**
|
|
465
|
-
|
|
466
|
-
```bash
|
|
467
|
-
#!/bin/bash
|
|
468
|
-
set -euo pipefail
|
|
469
|
-
source .buildkite/scripts/dashboard-helpers.sh
|
|
470
|
-
|
|
471
|
-
START=$(date +%s)
|
|
472
|
-
make lint
|
|
473
|
-
DURATION=$(($(date +%s) - START))
|
|
474
|
-
|
|
475
|
-
update_dashboard "Lint" ":white_check_mark:" "${DURATION}s"
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
---
|
|
479
|
-
|
|
480
|
-
## Secrets from external vault with redaction
|
|
481
|
-
|
|
482
|
-
Fetch secrets from HashiCorp Vault and redact them from build logs.
|
|
483
|
-
|
|
484
|
-
```bash
|
|
485
|
-
#!/bin/bash
|
|
486
|
-
set -euo pipefail
|
|
487
|
-
|
|
488
|
-
# Authenticate to Vault using Buildkite OIDC
|
|
489
|
-
VAULT_TOKEN=$(buildkite-agent oidc request-token --audience "https://vault.internal" \
|
|
490
|
-
| vault write -field=token auth/jwt/login role=buildkite jwt=-)
|
|
491
|
-
|
|
492
|
-
echo "$VAULT_TOKEN" | buildkite-agent redactor add
|
|
493
|
-
|
|
494
|
-
# Fetch application secrets
|
|
495
|
-
DB_PASSWORD=$(VAULT_TOKEN="$VAULT_TOKEN" vault kv get -field=password secret/myapp/db)
|
|
496
|
-
API_KEY=$(VAULT_TOKEN="$VAULT_TOKEN" vault kv get -field=key secret/myapp/api)
|
|
497
|
-
|
|
498
|
-
# Redact both values
|
|
499
|
-
echo "$DB_PASSWORD" | buildkite-agent redactor add
|
|
500
|
-
echo "$API_KEY" | buildkite-agent redactor add
|
|
501
|
-
|
|
502
|
-
# Export for use (values are now redacted in any log output)
|
|
503
|
-
export DB_PASSWORD API_KEY
|
|
504
|
-
|
|
505
|
-
# Use them safely
|
|
506
|
-
./scripts/deploy.sh
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
---
|
|
510
|
-
|
|
511
|
-
## Artifact chain across builds
|
|
512
|
-
|
|
513
|
-
Upload artifacts in a build step, then download them in a triggered child pipeline.
|
|
514
|
-
|
|
515
|
-
**Parent pipeline step:**
|
|
516
|
-
|
|
517
|
-
```bash
|
|
518
|
-
#!/bin/bash
|
|
519
|
-
set -euo pipefail
|
|
520
|
-
|
|
521
|
-
# Build the artifact
|
|
522
|
-
make build
|
|
523
|
-
buildkite-agent artifact upload "dist/app.tar.gz"
|
|
524
|
-
|
|
525
|
-
# Store the build ID so the child pipeline can reference it
|
|
526
|
-
buildkite-agent meta-data set "artifact-build-id" "${BUILDKITE_BUILD_ID}"
|
|
527
|
-
|
|
528
|
-
# Trigger child pipeline, passing the build ID
|
|
529
|
-
buildkite-agent pipeline upload <<YAML
|
|
530
|
-
steps:
|
|
531
|
-
- trigger: "deploy-pipeline"
|
|
532
|
-
label: ":rocket: Deploy"
|
|
533
|
-
build:
|
|
534
|
-
message: "Deploy from build ${BUILDKITE_BUILD_NUMBER}"
|
|
535
|
-
meta_data:
|
|
536
|
-
parent-build-id: "${BUILDKITE_BUILD_ID}"
|
|
537
|
-
YAML
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
**Child pipeline step:**
|
|
541
|
-
|
|
542
|
-
```bash
|
|
543
|
-
#!/bin/bash
|
|
544
|
-
set -euo pipefail
|
|
545
|
-
|
|
546
|
-
# Get parent build ID from meta-data (passed via trigger step)
|
|
547
|
-
PARENT_BUILD=$(buildkite-agent meta-data get "parent-build-id")
|
|
548
|
-
|
|
549
|
-
# Download artifact from parent build
|
|
550
|
-
buildkite-agent artifact download "dist/app.tar.gz" . --build "${PARENT_BUILD}"
|
|
551
|
-
|
|
552
|
-
# Deploy it
|
|
553
|
-
tar xzf dist/app.tar.gz
|
|
554
|
-
./scripts/deploy.sh
|
|
555
|
-
```
|