forked from strands-agents/harness-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
186 lines (176 loc) · 6.82 KB
/
Copy pathpython-integration-test.yml
File metadata and controls
186 lines (176 loc) · 6.82 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
name: "Python: Integration Test"
on:
pull_request_target:
branches: [main]
paths:
- 'strands-py/**'
- '.github/workflows/python-*'
merge_group:
types: [checks_requested]
# workflow_call entry — TRUST INVARIANT.
#
# Lets another workflow in this repo reuse the integ tests against an
# arbitrary `ref` while keeping AWS_*. The authorization-check below is
# skipped on this path because the only callers
# (release-python.yml / release-typescript.yml) are workflow_dispatch-
# gated, which already requires repo write access.
#
# Before adding another caller, check all of:
# 1. Cannot be triggered by an unauthenticated user or a fork
# (no pull_request; no pull_request_target without an auth gate;
# no push from non-main branches).
# 2. Cannot be coerced into a fork-PR ref. validate-call-ref below is
# the runtime guard, but condition 1 should make that unnecessary.
# 3. AWS_ROLE / STRANDS_INTEG_TEST_ROLE are scoped to least privilege.
workflow_call:
inputs:
ref:
required: true
type: string
jobs:
validate-call-ref:
name: Validate workflow_call ref
if: inputs.ref != ''
runs-on: ubuntu-latest
permissions:
contents: read
# Reject ref shapes that could check out untrusted code:
# `refs/pull/*` (fork-PR merge refs) and `owner:branch` (cross-repo
# refs) fail; plain branches and SHAs pass.
#
# We do not also block on `github.event.repository.fork`. That flag is
# only `true` when this workflow runs on a fork's own runner — which
# is a legitimate case (release-python.yml's `run_integ_tests: true`
# lets a fork-owner test the pipeline with their own secrets). The
# ref-shape check above is what actually rejects untrusted refs.
steps:
- name: Reject untrusted-shaped refs
env:
REF: ${{ inputs.ref }}
run: |
set -euo pipefail
case "$REF" in
refs/pull/*|*:*)
echo "::error::workflow_call ref '$REF' looks like a fork PR or cross-repo ref."
exit 1
;;
esac
echo "ref '$REF' passed shape check."
authorization-check:
name: Check access
needs: [validate-call-ref]
# `needs` only runs after non-skipped predecessors. validate-call-ref is
# skipped on pull_request_target / merge_group (inputs.ref is empty), so
# we use `if: always()` to ensure auth-check still runs there. On
# workflow_call, validate-call-ref must have succeeded.
if: |
always() &&
(needs.validate-call-ref.result == 'success' || needs.validate-call-ref.result == 'skipped')
permissions:
contents: read
runs-on: ubuntu-latest
outputs:
approval-env: ${{ steps.auth.outputs.approval-env }}
steps:
- name: Check Authorization
id: auth
uses: strands-agents/devtools/authorization-check@main
with:
# Skip on merge_group (gated by branch protection) and on
# workflow_call (the caller — release.yml — is workflow_dispatch
# gated, see the trigger comment above).
# `github.event_name` can't identify the release here — inside a
# reusable workflow it reports the caller's event, never
# 'workflow_call' — so key off `inputs.ref`, which only a
# workflow_call caller supplies (empty on pull_request_target /
# merge_group). Matches the validate-call-ref guard above.
skip-check: ${{ github.event_name == 'merge_group' || inputs.ref != '' }}
username: ${{ github.event.pull_request.user.login || 'invalid' }}
allowed-roles: 'maintain,triage,write,admin'
check-access-and-checkout:
name: Run integration tests
runs-on: ubuntu-latest
needs: authorization-check
if: always() && needs.authorization-check.result == 'success'
environment:
name: ${{ needs.authorization-check.outputs.approval-env }}
deployment: false
permissions:
id-token: write
pull-requests: read
contents: read
defaults:
run:
working-directory: strands-py
steps:
- name: Configure Credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ secrets.STRANDS_INTEG_TEST_ROLE }}
aws-region: us-east-1
mask-aws-account-id: true
- name: Checkout head commit
uses: actions/checkout@v7
with:
ref: ${{ inputs.ref || github.event.pull_request.head.sha }}
persist-credentials: false
allow-unsafe-pr-checkout: true # opt back into fork-PR checkout, blocked by default in checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install --no-cache-dir hatch
- name: Run integration tests
env:
AWS_REGION: us-east-1
AWS_REGION_NAME: us-east-1
STRANDS_TEST_API_KEYS_SECRET_NAME: ${{ secrets.STRANDS_TEST_API_KEYS_SECRET_NAME }}
id: tests
run: |
hatch test tests_integ
- name: Upload test results
if: always()
uses: actions/upload-artifact@v7
with:
name: test-results
path: strands-py/build/test-results.xml
upload-metrics:
runs-on: ubuntu-latest
needs: check-access-and-checkout
# Publishes to the team's CloudWatch via STRANDS_INTEG_TEST_ROLE. Only run
# when the integration-test job actually executed; on fork PRs the auth
# environment gate skips the test job and no test-results artifact is
# produced, so this job would otherwise fail on artifact download. The
# previous github.event.repository.fork guard did not catch this case
# because pull_request_target always evaluates that field against the base
# repo, which is never a fork.
if: needs.check-access-and-checkout.result == 'success' || needs.check-access-and-checkout.result == 'failure'
permissions:
id-token: write
contents: read
steps:
- name: Configure Credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ secrets.STRANDS_INTEG_TEST_ROLE }}
aws-region: us-east-1
mask-aws-account-id: true
- name: Checkout main
uses: actions/checkout@v7
with:
ref: main
sparse-checkout: |
.github/scripts
persist-credentials: false
- name: Download test results
uses: actions/download-artifact@v8
with:
name: test-results
- name: Publish test metrics to CloudWatch
env:
REPO_NAME: ${{ github.event.repository.name }}
run: |
pip install --no-cache-dir boto3
python .github/scripts/upload-integ-test-metrics.py test-results.xml "$REPO_NAME"