Skip to content

Deploy to DEV

Deploy to DEV #15

Workflow file for this run

name: Deploy to DEV
on:
workflow_dispatch:
inputs:
force_bootstrap:
description: 'Force CDK bootstrap (check if needed)'
required: false
default: false
type: boolean
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
build-and-push:
name: Build and Push Image
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
id-token: write
outputs:
image_tag: ${{ steps.semver.outputs.version }}
steps:
# Step 1: Checkout repository
- name: Checkout repository
uses: actions/checkout@v5
# Step 2: Setup Node.js using .nvmrc
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version-file: .nvmrc
cache: 'npm'
# Step 3: Configure AWS credentials for role and region
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN_DEV }}
role-session-name: deploy-nestjs-starter-dev
aws-region: ${{ vars.AWS_REGION }}
# Step 4: Install the app dependencies
- name: Install app dependencies
run: npm ci
# Step 5: Build the app
- name: Build application
run: npm run build
# Step 6: Run the app unit tests
- name: Run unit tests
run: npm run test
# Step 7: Install the infrastructure dependencies
- name: Install infrastructure dependencies
working-directory: ./infrastructure
run: npm ci
# Step 8: Create the infrastructure .env file from CDK_ENV_DEV variable
- name: Create infrastructure .env file
working-directory: ./infrastructure
run: |
echo "${{ vars.CDK_ENV_DEV }}" > .env
echo "✅ Infrastructure .env file created"
# Step 9: Build the infrastructure
- name: Build infrastructure
working-directory: ./infrastructure
run: npm run build
# Step 10: Bootstrap the CDK (if needed)
- name: Bootstrap CDK
working-directory: ./infrastructure
run: |
if [ "${{ inputs.force_bootstrap }}" = "true" ]; then
echo "🔄 Force bootstrapping CDK..."
npm run bootstrap
else
echo "⚡ Checking if CDK bootstrap is needed..."
# Try to describe the bootstrap stack to see if it exists
if ! aws cloudformation describe-stacks --stack-name CDKToolkit --region ${{ vars.AWS_REGION }} >/dev/null 2>&1; then
echo "🚀 CDK not bootstrapped, bootstrapping now..."
npm run bootstrap
else
echo "✅ CDK already bootstrapped, skipping..."
fi
fi
# Step 11: Synthesize the CDK stacks
- name: Synthesize CDK stacks
working-directory: ./infrastructure
run: npm run synth
# Step 12: Deploy the ECR CDK stack
- name: Deploy ECR stack
working-directory: ./infrastructure
run: |
echo "🚀 Deploying ECR stack..."
npx cdk deploy nestjs-starter-ecr-dev --require-approval never
echo "✅ ECR stack deployed successfully"
# Step 13: Generate semver tag
- name: Generate semver tag
id: semver
run: |
# Get version from package.json
PKG_VERSION=$(node -p "require('./package.json').version")
# Generate build metadata from GitHub Actions context
BUILD_NUMBER="${{ github.run_number }}"
BUILD_SHA="${{ github.sha }}"
SHORT_SHA="${BUILD_SHA:0:7}"
# Create semver-compatible tag for ECR (using hyphen instead of plus)
# ECR only allows: [a-zA-Z0-9-_.] characters
SEMVER="${PKG_VERSION}-build.${BUILD_NUMBER}.${SHORT_SHA}"
echo "Package version: ${PKG_VERSION}"
echo "Build number: ${BUILD_NUMBER}"
echo "Short SHA: ${SHORT_SHA}"
echo "Generated semver: ${SEMVER}"
echo "version=${SEMVER}" >> $GITHUB_OUTPUT
# Step 14: Build the app Docker image and publish it to ECR
- name: Build and push Docker image to ECR
run: |
# Get ECR repository URI
ECR_REPOSITORY_URI=$(aws ecr describe-repositories --repository-names nestjs-starter --region ${{ vars.AWS_REGION }} --query 'repositories[0].repositoryUri' --output text)
echo "ECR Repository URI: $ECR_REPOSITORY_URI"
# Login to ECR
aws ecr get-login-password --region ${{ vars.AWS_REGION }} | docker login --username AWS --password-stdin $ECR_REPOSITORY_URI
# Build and tag the image with both latest and semver tags
SEMVER_TAG="${{ steps.semver.outputs.version }}"
echo "🔨 Building Docker image..."
docker build -t $ECR_REPOSITORY_URI:latest -t $ECR_REPOSITORY_URI:$SEMVER_TAG .
# Push both tags
echo "📤 Pushing Docker image with tag: latest"
docker push $ECR_REPOSITORY_URI:latest
echo "📤 Pushing Docker image with tag: $SEMVER_TAG"
docker push $ECR_REPOSITORY_URI:$SEMVER_TAG
echo "✅ Docker images pushed successfully"
echo " - $ECR_REPOSITORY_URI:latest"
echo " - $ECR_REPOSITORY_URI:$SEMVER_TAG"
# Step 15: Clean up sensitive infrastructure files
- name: Clean up sensitive files
if: always()
working-directory: ./infrastructure
run: |
echo "🧹 Cleaning up sensitive files..."
rm -f .env
rm -rf cdk.out
echo "✅ Sensitive files cleaned up"
deploy:
name: Deploy to DEV
needs: build-and-push
uses: ./.github/workflows/release-reusable.yml
with:
image_tag: ${{ needs.build-and-push.outputs.image_tag }}
environment: dev
aws_region: ${{ vars.AWS_REGION }}
aws_role_arn: ${{ vars.AWS_ROLE_ARN_DEV }}
cdk_env_content: ${{ vars.CDK_ENV_DEV }}
permissions:
contents: read
id-token: write