Run 2: Workflows
Entry Criteria
Section titled “Entry Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | demo branch exists in arda-frontend-app | git ls-remote --heads https://github.com/Arda-cards/arda-frontend-app demo | Ref listed |
| 2 | CloudFormation export: AmplifyAppId | aws cloudformation list-exports --region us-east-1 --output text --query "Exports[?Name=='Alpha001-demo-I-AmplifyAppId'].Value" | An app ID string |
| 3 | CloudFormation export: AmplifyBranchName | aws cloudformation list-exports --region us-east-1 --output text --query "Exports[?Name=='Alpha001-demo-I-AmplifyBranchName'].Value" | demo |
| 4 | IAM role assumable from arda-frontend-app demo branch | Run 1 test-oidc.yaml workflow succeeded | sts get-caller-identity in workflow log |
| 5 | PR1 merged: infrastructure changes on main | gh pr list -R Arda-cards/infrastructure --state merged --search "frontend pipeline" | PR merged |
| 6 | purpose-configuration-action available | gh api repos/Arda-cards/purpose-configuration-action --jq .name | purpose-configuration-action |
| 7 | ARDA_PURPOSE_LOCATOR_READER_TOKEN org secret exists | Verify via GitHub Settings UI | Secret listed |
Artifact Specifications
Section titled “Artifact Specifications”| Artifact | Path | Format | Description |
|---|---|---|---|
| Deploy workflow | /arda-frontend-app/.github/workflows/deploy.yaml | GHA YAML | Main deployment workflow with sequential matrix |
| Redeploy workflow | /arda-frontend-app/.github/workflows/redeploy.yaml | GHA YAML | Manual single-partition redeploy |
| Reusable deployment workflow | /arda-frontend-app/.github/workflows/reusable_deployment.yaml | GHA YAML | Shared deployment logic |
| GitHub environments | arda-frontend-app GitHub settings | Config | dev, stage, demo, prod with protection rules |
Task List
Section titled “Task List”| # | Task | Persona | Depends On | Status | Acceptance Criteria |
|---|---|---|---|---|---|
| 2.1 | Create reusable_deployment.yaml on demo branch | Agent | — | Pending | Workflow file valid YAML; accepts partition, commit_sha, amplify_region inputs |
| 2.2 | Create deploy.yaml on demo branch | Agent | 2.1 | Pending | Workflow file valid YAML; workflow_dispatch trigger; matrix [demo]; calls reusable workflow |
| 2.3 | Create redeploy.yaml on demo branch | Agent | 2.1 | Pending | Workflow file valid YAML; workflow_dispatch with partition and commit_sha inputs |
| 2.4 | Configure GitHub environments | Operator | — | Pending | Environments dev, stage, demo, prod exist with correct protection rules |
| 2.5 | Delete test-oidc.yaml from demo branch | Agent | 2.1 | Pending | File removed |
| 2.6 | First deployment test: Trigger deploy.yaml on demo branch | Operator | 2.1–2.5 | Pending | Workflow succeeds; demo site at demo.alpha001.app.arda.cards updates |
Task Details
Section titled “Task Details”Task 2.1: Create reusable_deployment.yaml
Section titled “Task 2.1: Create reusable_deployment.yaml”Who: Agent
File: arda-frontend-app/.github/workflows/reusable_deployment.yaml
Branch: demo
This is the core deployment logic, called by both deploy.yaml and redeploy.yaml. Reference the operations repo’s reusable_deployment.yaml for the structural pattern.
name: "Reusable Frontend Deployment"on: workflow_call: inputs: partition: required: true type: string description: "Target partition (dev, stage, demo, prod)" commit_sha: required: false type: string default: "" description: "Specific commit SHA to deploy (empty = latest on connected branch)" amplify_region: required: false type: string default: "" description: "Override Amplify API region (empty = use aws_region from purpose-config)" secrets: PURPOSE_LOCATOR_TOKEN: required: true
jobs: deploy: name: "Deploy to ${{ inputs.partition }}" runs-on: ubuntu-latest environment: ${{ inputs.partition }} permissions: contents: read id-token: write steps: # 1. Fetch purpose-configuration - name: Fetch purpose configuration id: purpose uses: Arda-cards/purpose-configuration-action@v1 with: purpose: ${{ inputs.partition }} token: ${{ secrets.PURPOSE_LOCATOR_TOKEN }}
# 2. Derive frontend role ARN - name: Derive frontend role id: role run: | AWS_ROLE="${{ steps.purpose.outputs.aws_role }}" # Append FrontEnd to the role name FRONTEND_ROLE="${AWS_ROLE/GitHubAction/GitHubActionFrontEnd}" echo "frontend_role=${FRONTEND_ROLE}" >> "$GITHUB_OUTPUT"
# Parse infrastructure prefix (text before -API-GitHubAction) ROLE_NAME="${AWS_ROLE##*/}" INFRA_PREFIX="${ROLE_NAME%%-API-GitHubAction*}" echo "infrastructure=${INFRA_PREFIX}" >> "$GITHUB_OUTPUT"
# Determine Amplify region AMPLIFY_REGION="${{ inputs.amplify_region }}" if [[ -z "${AMPLIFY_REGION}" ]]; then AMPLIFY_REGION="${{ steps.purpose.outputs.aws_region }}" fi echo "amplify_region=${AMPLIFY_REGION}" >> "$GITHUB_OUTPUT"
# 3. Configure AWS credentials via OIDC - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ steps.role.outputs.frontend_role }} aws-region: ${{ steps.purpose.outputs.aws_region }}
# 4. Read CloudFormation exports (always from us-east-1) - name: Read Amplify parameters id: amplify run: | INFRA="${{ steps.role.outputs.infrastructure }}" PARTITION="${{ inputs.partition }}"
APP_ID="$(aws cloudformation list-exports \ --region us-east-1 --output text \ --query "Exports[?Name=='${INFRA}-${PARTITION}-I-AmplifyAppId'].Value")" echo "app_id=${APP_ID}" >> "$GITHUB_OUTPUT"
BRANCH_NAME="$(aws cloudformation list-exports \ --region us-east-1 --output text \ --query "Exports[?Name=='${INFRA}-${PARTITION}-I-AmplifyBranchName'].Value")" echo "branch_name=${BRANCH_NAME}" >> "$GITHUB_OUTPUT"
echo "::notice::Amplify App ID: ${APP_ID}, Branch: ${BRANCH_NAME}"
# 5. Start Amplify job - name: Start deployment id: start run: | AMPLIFY_REGION="${{ steps.role.outputs.amplify_region }}" COMMIT_SHA="${{ inputs.commit_sha }}"
START_ARGS=( --app-id "${{ steps.amplify.outputs.app_id }}" --branch-name "${{ steps.amplify.outputs.branch_name }}" --job-type RELEASE --region "${AMPLIFY_REGION}" )
if [[ -n "${COMMIT_SHA}" ]]; then START_ARGS+=(--commit-id "${COMMIT_SHA}") fi
RESULT="$(aws amplify start-job "${START_ARGS[@]}")" JOB_ID="$(echo "${RESULT}" | jq -r '.jobSummary.jobId')" echo "job_id=${JOB_ID}" >> "$GITHUB_OUTPUT" echo "::notice::Started job ${JOB_ID}"
# 6. Poll for completion - name: Wait for deployment run: | AMPLIFY_REGION="${{ steps.role.outputs.amplify_region }}" APP_ID="${{ steps.amplify.outputs.app_id }}" BRANCH="${{ steps.amplify.outputs.branch_name }}" JOB_ID="${{ steps.start.outputs.job_id }}"
while true; do STATUS="$(aws amplify get-job \ --app-id "${APP_ID}" \ --branch-name "${BRANCH}" \ --job-id "${JOB_ID}" \ --region "${AMPLIFY_REGION}" \ --query "job.summary.status" --output text)"
echo "Job ${JOB_ID} status: ${STATUS}"
case "${STATUS}" in SUCCEED) echo "::notice::Deployment succeeded" exit 0 ;; FAILED|CANCELLING|CANCELLED) echo "::error::Deployment failed with status: ${STATUS}" exit 1 ;; *) sleep 30 ;; esac doneNotes:
- The
purpose-configuration-actionstep reference (@v1) and output names (aws_role,aws_region) must be verified against the actual action in theArda-cards/purpose-configuration-actionrepository. Read the action’saction.ymlto confirm. - The CloudFormation export reads are always from
us-east-1(per directive). - The Amplify API calls use
amplify_regionwhich defaults toaws_regionfrom purpose-config but can be overridden (e.g.,us-east-2for prod).
Task 2.2: Create deploy.yaml
Section titled “Task 2.2: Create deploy.yaml”Who: Agent
File: arda-frontend-app/.github/workflows/deploy.yaml
Branch: demo
name: "Deploy Frontend"on: workflow_dispatch: # Manual trigger during development # After cutover: add workflow_run trigger on ci.yaml success on main
jobs: deploy: strategy: matrix: include: - partition: demo # NOTE: This is the development-phase matrix (demo only). # At cutover (Run 4, Task 4.3 / PR2), this expands to: # [dev, stage, demo, prod (amplify_region: us-east-2)] max-parallel: 1 fail-fast: true uses: ./.github/workflows/reusable_deployment.yaml with: partition: ${{ matrix.partition }} amplify_region: ${{ matrix.amplify_region || '' }} secrets: PURPOSE_LOCATOR_TOKEN: ${{ secrets.ARDA_PURPOSE_LOCATOR_READER_TOKEN }}Task 2.3: Create redeploy.yaml
Section titled “Task 2.3: Create redeploy.yaml”Who: Agent
File: arda-frontend-app/.github/workflows/redeploy.yaml
Branch: demo
name: "Redeploy Frontend"on: workflow_dispatch: inputs: partition: type: choice options: - dev - stage - demo - prod description: "Target partition" commit_sha: type: string required: true description: "Commit SHA on main to deploy"
jobs: # TODO (deferred to Run 4, Task 4.3 / PR2): Add CI status check step before deployment # Check commit status API; run CI inline if not available
redeploy: uses: ./.github/workflows/reusable_deployment.yaml with: partition: ${{ inputs.partition }} commit_sha: ${{ inputs.commit_sha }} amplify_region: ${{ inputs.partition == 'prod' && 'us-east-2' || '' }} secrets: PURPOSE_LOCATOR_TOKEN: ${{ secrets.ARDA_PURPOSE_LOCATOR_READER_TOKEN }}Note: The CI status check (REQ-WF-002 item 2) is marked as TODO for the development phase. It should be implemented before cutover. The check verifies CI passed for the SHA via the commit status API; if CI never ran, it either runs CI inline or aborts.
Task 2.4: Configure GitHub Environments
Section titled “Task 2.4: Configure GitHub Environments”Who: Operator
Via GitHub UI or CLI:
# Create environmentsgh api -X PUT repos/Arda-cards/arda-frontend-app/environments/devgh api -X PUT repos/Arda-cards/arda-frontend-app/environments/stagegh api -X PUT repos/Arda-cards/arda-frontend-app/environments/demogh api -X PUT repos/Arda-cards/arda-frontend-app/environments/prodFor stage and prod, configure required_reviewers via the GitHub UI:
- Reviewers: denisa, jmpicnic, danmerb, davequinta
The GitHub API for environment protection rules requires admin access. Use the GitHub UI Settings → Environments for the reviewer configuration.
Task 2.5: Delete test-oidc.yaml
Section titled “Task 2.5: Delete test-oidc.yaml”Who: Agent
Remove arda-frontend-app/.github/workflows/test-oidc.yaml from the demo branch (created in Run 1 for OIDC verification).
Task 2.6: First Deployment Test
Section titled “Task 2.6: First Deployment Test”Who: Operator
- Push all workflow files to the
demobranch. - Go to GitHub Actions → “Deploy Frontend” → “Run workflow” → select
demobranch. - Monitor the workflow run. Verify in the logs:
- Purpose-configuration fetch succeeded (check logged partition — not secret values)
- OIDC role assumption succeeded (
aws sts get-caller-identityoutput) StartJobreturned ajobIdGetJobpolling shows status progressing toSUCCEED
- Visit
demo.alpha001.app.arda.cardsand verify the page loads. - Check the Amplify Console for the demo app: confirm the build was triggered by the
StartJobcall (not auto-build).
Internal Dependency Graph
Section titled “Internal Dependency Graph”2.1 (reusable_deployment.yaml) ──┬──→ 2.2 (deploy.yaml) ├──→ 2.3 (redeploy.yaml) └──→ 2.5 (delete test-oidc.yaml)2.4 (GitHub environments) ──→ (independent, can be done in parallel)
All above ──→ 2.6 (First deployment test)Exit Criteria
Section titled “Exit Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | reusable_deployment.yaml exists on demo branch | gh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/reusable_deployment.yaml?ref=demo --jq .name | reusable_deployment.yaml |
| 2 | deploy.yaml exists on demo branch | gh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/deploy.yaml?ref=demo --jq .name | deploy.yaml |
| 3 | redeploy.yaml exists on demo branch | gh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/redeploy.yaml?ref=demo --jq .name | redeploy.yaml |
| 4 | test-oidc.yaml deleted | gh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/test-oidc.yaml?ref=demo 2>&1 | 404 |
| 5 | GitHub environments configured | gh api repos/Arda-cards/arda-frontend-app/environments --jq '.environments[].name' | dev, stage, demo, prod |
| 6 | deploy.yaml succeeded at least once | gh run list -R Arda-cards/arda-frontend-app -w "Deploy Frontend" --branch demo --status success -L 1 --json conclusion -q '.[0].conclusion' | success |
| 7 | Demo site loads | curl -s -o /dev/null -w "%{http_code}" https://demo.alpha001.app.arda.cards | 200 |
Handoff
Section titled “Handoff”Artifacts Consumed (from previous runs)
Section titled “Artifacts Consumed (from previous runs)”| Artifact | Source Run | Path/Location |
|---|---|---|
demo branch | Run 1 | arda-frontend-app repo |
| CloudFormation exports (demo) | Run 1 | Alpha001-demo-I-AmplifyAppId, Alpha001-demo-I-AmplifyBranchName |
| IAM role (Alpha001) | Run 1 | Alpha001-API-GitHubActionFrontEnd |
test-oidc.yaml (to delete) | Run 1 | arda-frontend-app/.github/workflows/test-oidc.yaml |
Artifacts Produced (for subsequent runs)
Section titled “Artifacts Produced (for subsequent runs)”| Artifact | Consumer Run | Path/Location |
|---|---|---|
deploy.yaml | Run 3, Run 4 | arda-frontend-app/.github/workflows/deploy.yaml |
redeploy.yaml | Run 3, Run 4 | arda-frontend-app/.github/workflows/redeploy.yaml |
reusable_deployment.yaml | Run 3, Run 4 | arda-frontend-app/.github/workflows/reusable_deployment.yaml |
| GitHub environments | Run 3, Run 4 | arda-frontend-app GitHub settings |
Copyright: © Arda Systems 2025-2026, All rights reserved