Secure Integration test workflow (aws/bedrock-agentcore-starter-toolkit)
The Secure Integration test workflow from aws/bedrock-agentcore-starter-toolkit, explained and optimized by Latchkey.
CI health: F - at risk
Point runs-on at Latchkey and get caching, run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Secure Integration test workflow from the aws/bedrock-agentcore-starter-toolkit repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Secure Integration test
on:
push:
branches: [ main ]
tags:
- 'v*'
pull_request_target: # Changed from pull_request
branches: [ main ]
types: [opened, synchronize, reopened]
permissions:
contents: read
jobs:
authorization-check:
permissions: read-all
runs-on: ubuntu-latest
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@v5
with:
ref: ${{ github.event.pull_request.base.sha }}
- name: Safety Check - Prevent Workflow Modification Attacks
id: safety-check
uses: actions/github-script@v7
with:
result-encoding: string
script: |
if (!context.payload.pull_request) {
console.log('Not a pull request, proceeding');
return 'true';
}
// Get list of changed files
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});
// Check if any workflow files or sensitive files are modified
const dangerousPatterns = [
/^\.github\/workflows\//,
/^\.github\/actions\//,
/conftest\.py$/,
/pytest\.ini$/,
/^tests\/conftest_mock\.py$/,
];
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@v7
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:
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
pull-requests: read
contents: read
steps:
- name: Configure Credentials
uses: aws-actions/configure-aws-credentials@v5
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@v5
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@v5
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install -e .
pip install --no-cache-dir pytest click
- name: Run integration tests
env:
AWS_REGION: us-west-2
AGENTCORE_TEST_ROLE: AgentExecutionRole
id: tests
timeout-minutes: 10
run: |
pytest tests_integ/cli -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
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: Secure Integration test on: push: branches: [ main ] tags: - 'v*' pull_request_target: # Changed from pull_request branches: [ main ] types: [opened, synchronize, reopened] permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: authorization-check: timeout-minutes: 30 permissions: read-all runs-on: latchkey-small 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@v5 with: ref: ${{ github.event.pull_request.base.sha }} - name: Safety Check - Prevent Workflow Modification Attacks id: safety-check uses: actions/github-script@v7 with: result-encoding: string script: | if (!context.payload.pull_request) { console.log('Not a pull request, proceeding'); return 'true'; } // Get list of changed files const { data: files } = await github.rest.pulls.listFiles({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request.number, }); // Check if any workflow files or sensitive files are modified const dangerousPatterns = [ /^\.github\/workflows\//, /^\.github\/actions\//, /conftest\.py$/, /pytest\.ini$/, /^tests\/conftest_mock\.py$/, ]; 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@v7 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: timeout-minutes: 30 runs-on: latchkey-small needs: authorization-check if: needs.authorization-check.outputs.should-run == 'true' environment: ${{ needs.authorization-check.outputs.approval-env }} permissions: id-token: write pull-requests: read contents: read steps: - name: Configure Credentials uses: aws-actions/configure-aws-credentials@v5 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@v5 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@v5 with: cache: 'pip' python-version: '3.10' - name: Install dependencies run: | pip install -e . pip install --no-cache-dir pytest click - name: Run integration tests env: AWS_REGION: us-west-2 AGENTCORE_TEST_ROLE: AgentExecutionRole id: tests timeout-minutes: 10 run: | pytest tests_integ/cli -s --log-cli-level=INFO safety-gate: timeout-minutes: 30 runs-on: latchkey-small 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
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.