-
Notifications
You must be signed in to change notification settings - Fork 108
202 lines (185 loc) · 7.41 KB
/
integration-testing.yml
File metadata and controls
202 lines (185 loc) · 7.41 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
name: Secure Integration test
on:
push:
branches: [ main ]
tags:
- 'v*'
pull_request_target:
branches: [ main ]
types: [opened, synchronize, reopened]
# Global permissions - most restrictive by default
permissions:
contents: read
jobs:
authorization-check:
permissions: read-all
runs-on: ubuntu-latest
# Skip entirely for Dependabot PRs — they are not collaborators so they
# would always route to manual-approval, blocking auto-merge indefinitely.
# Dependabot PRs are validated by ci.yml (lint, test, build) which are
# the required status checks in the main-status-checks Ruleset.
if: github.actor != 'dependabot[bot]'
outputs:
approval-env: ${{ steps.collab-check.outputs.result }}
should-run: ${{ steps.safety-check.outputs.result }}
steps:
- name: Checkout base branch for safety check
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.base.sha }}
- name: Safety Check - Prevent Workflow Modification Attacks
id: safety-check
uses: actions/github-script@v8
with:
result-encoding: string
script: |
if (!context.payload.pull_request) {
console.log('Not a pull request, proceeding');
return 'true';
}
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});
const dangerousPatterns = [
/^\.github\/workflows\//,
/^\.github\/actions\//,
/conftest\.py$/,
/pytest\.ini$/,
];
const dangerousFiles = files.filter(file =>
dangerousPatterns.some(pattern => pattern.test(file.filename))
);
if (dangerousFiles.length > 0) {
console.log('⚠️ SECURITY: PR modifies sensitive files:');
dangerousFiles.forEach(f => console.log(` - ${f.filename}`));
console.log('Manual review required before running integration tests');
return 'false';
}
console.log('✓ Safety check passed - no sensitive files modified');
return 'true';
- name: Collaborator Check
uses: actions/github-script@v8
id: collab-check
with:
result-encoding: string
script: |
try {
let username;
if (context.payload.pull_request) {
username = context.payload.pull_request.user.login;
} else {
username = context.actor;
console.log(`No pull request context found, checking permissions for actor: ${username}`);
}
const permissionResponse = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: username,
});
const permission = permissionResponse.data.permission;
const hasWriteAccess = ['write', 'admin'].includes(permission);
if (!hasWriteAccess) {
console.log(`User ${username} does not have write access to the repository (permission: ${permission})`);
return "manual-approval"
} else {
console.log(`Verified ${username} has write access. Auto Approving PR Checks.`)
return "auto-approve"
}
} catch (error) {
console.log(`${username} does not have write access. Requiring Manual Approval to run PR Checks.`)
return "manual-approval"
}
check-access-and-checkout:
name: Test (${{ matrix.group }})
runs-on: ubuntu-latest
needs: authorization-check
if: needs.authorization-check.outputs.should-run == 'true'
environment: ${{ needs.authorization-check.outputs.approval-env }}
permissions:
id-token: write # Required for AWS OIDC
pull-requests: read # Required to read PR info
contents: read # Required to checkout code
strategy:
fail-fast: false
matrix:
include:
- group: runtime
path: tests_integ/runtime
timeout: 10
extra-deps: ""
ignore: ""
# TODO: expand to full tests_integ/memory once test stability is addressed
- group: memory
path: tests_integ/memory/test_controlplane.py tests_integ/memory/test_memory_client.py tests_integ/memory/integrations/test_session_manager.py
timeout: 15
extra-deps: ""
ignore: ""
- group: evaluation
path: tests_integ/evaluation
timeout: 15
extra-deps: "strands-agents-evals"
ignore: ""
- group: services
path: tests_integ/services
timeout: 5
extra-deps: ""
ignore: ""
steps:
- name: Configure Credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ secrets.AGENTCORE_INTEG_TEST_ROLE }}
aws-region: us-west-2
mask-aws-account-id: true
- name: Checkout PR head commit
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install -e .
pip install --no-cache-dir pytest pytest-xdist pytest-order pytest-rerunfailures requests strands-agents uvicorn httpx starlette websockets ${{ matrix.extra-deps }}
- name: Run integration tests
env:
AWS_REGION: us-west-2
PYTHONUNBUFFERED: 1
MEMORY_KINESIS_ARN: ${{ secrets.MEMORY_KINESIS_ARN }}
MEMORY_ROLE_ARN: ${{ secrets.MEMORY_ROLE_ARN }}
MEMORY_PREPOPULATED_ID: ${{ secrets.MEMORY_PREPOPULATED_ID }}
RESOURCE_POLICY_TEST_ARN: ${{ secrets.RESOURCE_POLICY_TEST_ARN }}
RESOURCE_POLICY_TEST_PRINCIPAL: ${{ secrets.RESOURCE_POLICY_TEST_PRINCIPAL }}
id: tests
timeout-minutes: ${{ matrix.timeout }}
run: |
pytest ${{ matrix.path }} ${{ matrix.ignore }} -n auto --dist=loadscope -s --log-cli-level=INFO
safety-gate:
runs-on: ubuntu-latest
needs: authorization-check
if: needs.authorization-check.outputs.should-run == 'false'
permissions: {}
steps:
- name: Security Block
run: |
echo "🚨 SECURITY BLOCK: This PR modifies sensitive files"
echo ""
echo "The following types of files trigger manual review:"
echo " - Workflow files (.github/workflows/)"
echo " - Action files (.github/actions/)"
echo " - Test setup files (conftest.py, pytest.ini)"
echo ""
echo "⚠️ Integration tests will NOT run automatically"
echo "👀 A maintainer must review the changes and manually trigger tests"
echo ""
echo "This is a security measure to prevent:"
echo " - Workflow modification attacks"
echo " - Secret exfiltration"
echo " - Test manipulation"
exit 1