-
Notifications
You must be signed in to change notification settings - Fork 156
149 lines (138 loc) · 6.35 KB
/
Copy pathsynthetic-probes.yml
File metadata and controls
149 lines (138 loc) · 6.35 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
name: Synthetic probes (staging)
# Synthetic probes for nester#1056.
#
# Real-traffic SLIs cannot see a flow that is broken while nobody is using it.
# These probes exercise deposit, withdrawal, and balance read on a schedule
# so a broken path is found by us rather than by the first user who tries it.
#
# Every 15 minutes rather than every 5: the mutating probes create real
# testnet transactions, and a tighter cadence multiplies that cost for very
# little detection benefit. The SyntheticProbeStale alert allows 30 minutes,
# which tolerates one missed run before complaining.
on:
schedule:
- cron: "*/15 * * * *"
workflow_dispatch:
inputs:
allow_mutations:
description: >-
Run the deposit and withdrawal probes, which create real staging
transactions. Leave false for a read-only run.
type: boolean
default: false
permissions:
contents: read
concurrency:
# Never overlap runs. Two concurrent deposit probes against the same vault
# would interleave and produce failures that describe the probes rather than
# the service.
group: synthetic-probes
cancel-in-progress: false
jobs:
probe:
name: Probe staging
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
# A missing secret must never let a probe fall back to localhost or to
# production. probe.py refuses to guess a target on its own; this guard
# keeps the run from being reported as a failure when it is simply not
# configured yet. Same pattern as the load-soak workflow.
- name: Check staging target is configured
id: guard
env:
API_BASE_URL: ${{ secrets.STAGING_PROBE_API_BASE_URL }}
AUTH_TOKEN: ${{ secrets.STAGING_PROBE_AUTH_TOKEN }}
VAULT_ID: ${{ secrets.STAGING_PROBE_VAULT_ID }}
run: |
all_set=true
for var in API_BASE_URL AUTH_TOKEN VAULT_ID; do
if [ -z "$(eval echo \$$var)" ]; then
echo "::notice::STAGING_PROBE_${var} is not set — skipping the probe run."
all_set=false
fi
done
if [ "$all_set" = "true" ]; then
echo "configured=true" >> "$GITHUB_OUTPUT"
else
echo "configured=false" >> "$GITHUB_OUTPUT"
# Surfaced in the job summary, not only as an annotation. The
# guard requires all three secrets, so a partially-configured
# environment disables every probe while the workflow still
# reports green — the state most likely to be mistaken for
# "probes are running and finding nothing".
{
echo "### Synthetic probes skipped"
echo
echo "Not all STAGING_PROBE_* secrets are configured, so no probe ran."
echo "Monitoring is **not** active for this run. See docs/ci/secrets.md."
} >> "$GITHUB_STEP_SUMMARY"
fi
- name: Run synthetic probes
id: probes
if: steps.guard.outputs.configured == 'true'
continue-on-error: true
# continue-on-error allows the Pushgateway push (below) to happen even
# if probes fail, so metrics are always published for alerting. The
# actual build gate is the "Report probe failure" step that follows,
# which exits 1 if this step failed. This ensures failures are visible
# in both the Actions UI and through alerting metrics.
env:
PROBE_API_BASE_URL: ${{ secrets.STAGING_PROBE_API_BASE_URL }}
PROBE_AUTH_TOKEN: ${{ secrets.STAGING_PROBE_AUTH_TOKEN }}
PROBE_VAULT_ID: ${{ secrets.STAGING_PROBE_VAULT_ID }}
PROBE_ENVIRONMENT: staging
PROBE_AMOUNT: ${{ vars.STAGING_PROBE_AMOUNT || '0.01' }}
# Mutating probes are opt-in. The scheduled run is read-only unless
# STAGING_PROBE_ALLOW_MUTATIONS is set for this environment, so
# enabling money movement is a deliberate configuration act rather
# than a side effect of merging this workflow.
PROBE_ALLOW_MUTATIONS: >-
${{ inputs.allow_mutations && 'true'
|| vars.STAGING_PROBE_ALLOW_MUTATIONS || 'false' }}
run: |
mkdir -p results
python tests/probes/probe.py --output results/probes.prom
# Pushed separately from the probe run, and only when a gateway is
# configured. The probe's own exit code is not the signal here: a failed
# probe still has results worth publishing, which is why the run step
# uses continue-on-error and the alerting is driven by the metrics.
- name: Push probe results
if: steps.guard.outputs.configured == 'true'
env:
PUSHGATEWAY_URL: ${{ secrets.STAGING_PUSHGATEWAY_URL }}
PUSHGATEWAY_AUTH: ${{ secrets.STAGING_PUSHGATEWAY_AUTH }}
run: |
set -euo pipefail
# Checked here rather than in the step's `if`: a step's own `env`
# block is not available to its condition, so the expression would
# silently evaluate to empty and skip the push every time.
if [ -z "${PUSHGATEWAY_URL:-}" ]; then
echo "::notice::STAGING_PUSHGATEWAY_URL is not set — probe results not pushed."
exit 0
fi
auth_args=()
if [ -n "${PUSHGATEWAY_AUTH:-}" ]; then
auth_args=(--header "Authorization: Bearer ${PUSHGATEWAY_AUTH}")
fi
curl -sSf --max-time 30 "${auth_args[@]}" \
--data-binary @results/probes.prom \
"${PUSHGATEWAY_URL%/}/metrics/job/nester_synthetic_probes/environment/staging"
- uses: actions/upload-artifact@v4
if: always() && steps.guard.outputs.configured == 'true'
with:
name: probe-results-${{ github.run_id }}
path: results/probes.prom
if-no-files-found: warn
# The workflow fails after publishing, so a failed probe is visible in
# the Actions UI as well as through alerting. Publishing first means a
# failure never costs us the metrics that explain it.
- name: Report probe failure
if: steps.guard.outputs.configured == 'true' && steps.probes.outcome == 'failure'
run: |
echo "::error::One or more synthetic probes failed. See the run log and results/probes.prom."
exit 1