Initial commit #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy to AWS | ||
| # Comment this out to enable the CI/CD pipeline | ||
| on: | ||
| #push: | ||
| # branches: [main] | ||
| jobs: | ||
| deploy: | ||
| name: Build and Deploy to EC2 | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| id-token: write | ||
| contents: read | ||
| env: | ||
| AWS_REGION: us-east-1 | ||
| GITHUB_ROLE_ARN: arn:aws:iam::962926148312:role/seed-github-actions-role | ||
| PROJECT_NAME: seed | ||
| DB_NAME: seeddb | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Set up JDK 21 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| java-version: '21' | ||
| distribution: 'temurin' | ||
| - name: Grant Gradle execute permission | ||
| run: chmod +x gradlew | ||
| - name: Build JAR with Gradle | ||
| run: ./gradlew clean build -x test | ||
| - name: Verify built artifacts exist | ||
| run: | | ||
| test -f Dockerfile | ||
| test -f scripts/start-app.sh | ||
| ls -l build/libs/*.jar | ||
| - name: Configure AWS credentials via OIDC | ||
| uses: aws-actions/configure-aws-credentials@v4 | ||
| with: | ||
| role-to-assume: ${{ env.GITHUB_ROLE_ARN }} | ||
| aws-region: ${{ env.AWS_REGION }} | ||
| - name: Retrieve deployment values from SSM | ||
| id: fetch_params | ||
| run: | | ||
| EC2_INSTANCE_ID=$(aws ssm get-parameter --name /seed/ec2_instance_id --with-decryption --query Parameter.Value --output text) | ||
| RDS_ENDPOINT=$(aws ssm get-parameter --name /seed/rds_endpoint --with-decryption --query Parameter.Value --output text) | ||
| DEPLOYMENT_BUCKET=$(aws ssm get-parameter --name /seed/deployment_bucket --with-decryption --query Parameter.Value --output text) | ||
| DB_PASSWORD=$(aws ssm get-parameter --name /seed/db_password --with-decryption --query Parameter.Value --output text) | ||
| echo "::add-mask::$DB_PASSWORD" | ||
| echo "::add-mask::$DEPLOYMENT_BUCKET" | ||
| echo "::add-mask::$RDS_ENDPOINT" | ||
| echo "EC2_INSTANCE_ID=$EC2_INSTANCE_ID" >> $GITHUB_ENV | ||
| echo "RDS_ENDPOINT=$RDS_ENDPOINT" >> $GITHUB_ENV | ||
| echo "DEPLOYMENT_BUCKET=$DEPLOYMENT_BUCKET" >> $GITHUB_ENV | ||
| echo "DB_PASSWORD=$DB_PASSWORD" >> $GITHUB_ENV | ||
| - name: Get JAR filename | ||
| run: | | ||
| JAR_FILE=$(ls build/libs/*.jar | grep -v plain) | ||
| echo "JAR_FILE=$JAR_FILE" >> $GITHUB_ENV | ||
| ls -lh "$JAR_FILE" | ||
| - name: Upload deployment artifacts to S3 | ||
| run: | | ||
| aws s3 cp "$JAR_FILE" s3://$DEPLOYMENT_BUCKET/deployments/app.jar | ||
| aws s3 cp Dockerfile s3://$DEPLOYMENT_BUCKET/deployments/Dockerfile | ||
| aws s3 cp scripts/start-app.sh s3://$DEPLOYMENT_BUCKET/deployments/start-app.sh | ||
| - name: Generate SSM parameters JSON | ||
| run: | | ||
| cat <<EOF > ssm-params.json | ||
| { | ||
| "commands": [ | ||
| "#!/bin/bash", | ||
| "set -eux", | ||
| "export PROJECT_NAME=$PROJECT_NAME", | ||
| "export DB_NAME=$DB_NAME", | ||
| "docker stop seed || true", | ||
| "docker rm seed || true", | ||
| "rm -rf /home/ec2-user/app", | ||
| "mkdir -p /home/ec2-user/app", | ||
| "aws s3 cp s3://$DEPLOYMENT_BUCKET/deployments/app.jar /home/ec2-user/app/app.jar", | ||
| "aws s3 cp s3://$DEPLOYMENT_BUCKET/deployments/Dockerfile /home/ec2-user/app/Dockerfile", | ||
| "aws s3 cp s3://$DEPLOYMENT_BUCKET/deployments/start-app.sh /home/ec2-user/app/start-app.sh", | ||
| "chmod +x /home/ec2-user/app/start-app.sh", | ||
| "export DB_URL=jdbc:postgresql://$RDS_ENDPOINT/$DB_NAME", | ||
| "export DB_USERNAME=seeddbadmin", | ||
| "export DB_PASSWORD=$DB_PASSWORD", | ||
| "bash /home/ec2-user/app/start-app.sh" | ||
| ] | ||
| } | ||
| EOF | ||
| - name: Run remote deployment via SSM | ||
| id: deploy_ssm | ||
| run: | | ||
| set -euo pipefail | ||
| COMMAND_ID=$(aws ssm send-command \ | ||
| --document-name AWS-RunShellScript \ | ||
| --instance-ids $EC2_INSTANCE_ID \ | ||
| --comment "Deploy seed app" \ | ||
| --parameters file://ssm-params.json \ | ||
| --output-s3-bucket-name $DEPLOYMENT_BUCKET \ | ||
| --output-s3-key-prefix ssm-logs/$EC2_INSTANCE_ID \ | ||
| --region $AWS_REGION \ | ||
| --query "Command.CommandId" \ | ||
| --output text) | ||
| echo "command_id=$COMMAND_ID" >> $GITHUB_OUTPUT | ||
| - name: Debug SSM invocation | ||
| run: | | ||
| CMD_ID=${{ steps.deploy_ssm.outputs.command_id }} | ||
| echo "🔍 SSM Command ID: $CMD_ID" | ||
| echo "--- Invocation details ---" | ||
| aws ssm list-command-invocations \ | ||
| --command-id "$CMD_ID" \ | ||
| --details \ | ||
| --region "$AWS_REGION" | ||
| echo "--- Last invocation output ---" | ||
| aws ssm get-command-invocation \ | ||
| --command-id "$CMD_ID" \ | ||
| --instance-id "$EC2_INSTANCE_ID" \ | ||
| --region "$AWS_REGION" \ | ||
| --query "{Status:Status, StdOut:StandardOutputContent, StdErr:StandardErrorContent}" \ | ||
| --output json | ||
| - name: Wait for SSM command to finish & show logs | ||
| run: | | ||
| set -euo pipefail | ||
| CMD_ID=${{ steps.deploy_ssm.outputs.command_id }} | ||
| STATUS="" | ||
| while [[ "$STATUS" != "Success" && "$STATUS" != "Cancelled" && "$STATUS" != "Failed" ]]; do | ||
| sleep 5 | ||
| STATUS=$(aws ssm get-command-invocation \ | ||
| --region "$AWS_REGION" \ | ||
| --command-id "$CMD_ID" \ | ||
| --instance-id "$EC2_INSTANCE_ID" \ | ||
| --query "Status" \ | ||
| --output text) | ||
| echo "📦 Current status: $STATUS" | ||
| done | ||
| echo "📄 StandardOutput:" | ||
| aws ssm get-command-invocation \ | ||
| --region "$AWS_REGION" \ | ||
| --command-id "$CMD_ID" \ | ||
| --instance-id "$EC2_INSTANCE_ID" \ | ||
| --query "StandardOutputContent" \ | ||
| --output text | ||
| echo "❌ StandardError:" | ||
| aws ssm get-command-invocation \ | ||
| --region "$AWS_REGION" \ | ||
| --command-id "$CMD_ID" \ | ||
| --instance-id "$EC2_INSTANCE_ID" \ | ||
| --query "StandardErrorContent" \ | ||
| --output text | ||