Skip to content

Run 2: Workflows

#CriterionVerification CommandExpected Output
1demo branch exists in arda-frontend-appgit ls-remote --heads https://github.com/Arda-cards/arda-frontend-app demoRef listed
2CloudFormation export: AmplifyAppIdaws cloudformation list-exports --region us-east-1 --output text --query "Exports[?Name=='Alpha001-demo-I-AmplifyAppId'].Value"An app ID string
3CloudFormation export: AmplifyBranchNameaws cloudformation list-exports --region us-east-1 --output text --query "Exports[?Name=='Alpha001-demo-I-AmplifyBranchName'].Value"demo
4IAM role assumable from arda-frontend-app demo branchRun 1 test-oidc.yaml workflow succeededsts get-caller-identity in workflow log
5PR1 merged: infrastructure changes on maingh pr list -R Arda-cards/infrastructure --state merged --search "frontend pipeline"PR merged
6purpose-configuration-action availablegh api repos/Arda-cards/purpose-configuration-action --jq .namepurpose-configuration-action
7ARDA_PURPOSE_LOCATOR_READER_TOKEN org secret existsVerify via GitHub Settings UISecret listed
ArtifactPathFormatDescription
Deploy workflow/arda-frontend-app/.github/workflows/deploy.yamlGHA YAMLMain deployment workflow with sequential matrix
Redeploy workflow/arda-frontend-app/.github/workflows/redeploy.yamlGHA YAMLManual single-partition redeploy
Reusable deployment workflow/arda-frontend-app/.github/workflows/reusable_deployment.yamlGHA YAMLShared deployment logic
GitHub environmentsarda-frontend-app GitHub settingsConfigdev, stage, demo, prod with protection rules
#TaskPersonaDepends OnStatusAcceptance Criteria
2.1Create reusable_deployment.yaml on demo branchAgentPendingWorkflow file valid YAML; accepts partition, commit_sha, amplify_region inputs
2.2Create deploy.yaml on demo branchAgent2.1PendingWorkflow file valid YAML; workflow_dispatch trigger; matrix [demo]; calls reusable workflow
2.3Create redeploy.yaml on demo branchAgent2.1PendingWorkflow file valid YAML; workflow_dispatch with partition and commit_sha inputs
2.4Configure GitHub environmentsOperatorPendingEnvironments dev, stage, demo, prod exist with correct protection rules
2.5Delete test-oidc.yaml from demo branchAgent2.1PendingFile removed
2.6First deployment test: Trigger deploy.yaml on demo branchOperator2.1–2.5PendingWorkflow succeeds; demo site at demo.alpha001.app.arda.cards updates

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
done

Notes:

  • The purpose-configuration-action step reference (@v1) and output names (aws_role, aws_region) must be verified against the actual action in the Arda-cards/purpose-configuration-action repository. Read the action’s action.yml to confirm.
  • The CloudFormation export reads are always from us-east-1 (per directive).
  • The Amplify API calls use amplify_region which defaults to aws_region from purpose-config but can be overridden (e.g., us-east-2 for prod).

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 }}

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.

Who: Operator

Via GitHub UI or CLI:

Terminal window
# Create environments
gh api -X PUT repos/Arda-cards/arda-frontend-app/environments/dev
gh api -X PUT repos/Arda-cards/arda-frontend-app/environments/stage
gh api -X PUT repos/Arda-cards/arda-frontend-app/environments/demo
gh api -X PUT repos/Arda-cards/arda-frontend-app/environments/prod

For 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.

Who: Agent

Remove arda-frontend-app/.github/workflows/test-oidc.yaml from the demo branch (created in Run 1 for OIDC verification).

Who: Operator

  1. Push all workflow files to the demo branch.
  2. Go to GitHub Actions → “Deploy Frontend” → “Run workflow” → select demo branch.
  3. 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-identity output)
    • StartJob returned a jobId
    • GetJob polling shows status progressing to SUCCEED
  4. Visit demo.alpha001.app.arda.cards and verify the page loads.
  5. Check the Amplify Console for the demo app: confirm the build was triggered by the StartJob call (not auto-build).
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)
#CriterionVerification CommandExpected Output
1reusable_deployment.yaml exists on demo branchgh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/reusable_deployment.yaml?ref=demo --jq .namereusable_deployment.yaml
2deploy.yaml exists on demo branchgh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/deploy.yaml?ref=demo --jq .namedeploy.yaml
3redeploy.yaml exists on demo branchgh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/redeploy.yaml?ref=demo --jq .nameredeploy.yaml
4test-oidc.yaml deletedgh api repos/Arda-cards/arda-frontend-app/contents/.github/workflows/test-oidc.yaml?ref=demo 2>&1404
5GitHub environments configuredgh api repos/Arda-cards/arda-frontend-app/environments --jq '.environments[].name'dev, stage, demo, prod
6deploy.yaml succeeded at least oncegh run list -R Arda-cards/arda-frontend-app -w "Deploy Frontend" --branch demo --status success -L 1 --json conclusion -q '.[0].conclusion'success
7Demo site loadscurl -s -o /dev/null -w "%{http_code}" https://demo.alpha001.app.arda.cards200
ArtifactSource RunPath/Location
demo branchRun 1arda-frontend-app repo
CloudFormation exports (demo)Run 1Alpha001-demo-I-AmplifyAppId, Alpha001-demo-I-AmplifyBranchName
IAM role (Alpha001)Run 1Alpha001-API-GitHubActionFrontEnd
test-oidc.yaml (to delete)Run 1arda-frontend-app/.github/workflows/test-oidc.yaml
ArtifactConsumer RunPath/Location
deploy.yamlRun 3, Run 4arda-frontend-app/.github/workflows/deploy.yaml
redeploy.yamlRun 3, Run 4arda-frontend-app/.github/workflows/redeploy.yaml
reusable_deployment.yamlRun 3, Run 4arda-frontend-app/.github/workflows/reusable_deployment.yaml
GitHub environmentsRun 3, Run 4arda-frontend-app GitHub settings