ci: add CI/CD pipeline via OpsTools #4
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: Node.js API CI/CD Pipeline | ||
| on: | ||
| push: | ||
| branches: | ||
| - main | ||
| - develop | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| - develop | ||
| env: | ||
| AWS_REGION: us-east-1 | ||
| ECR_REPOSITORY: node-api | ||
| ECS_SERVICE: node-api-service | ||
| ECS_CLUSTER: node-api-cluster | ||
| ECS_TASK_DEFINITION: node-api-task | ||
| jobs: | ||
| lint-test: | ||
| name: Lint and Test | ||
| runs-on: ubuntu-22.04 | ||
| strategy: | ||
| matrix: | ||
| node-version: [18.x, 20.x] | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 | ||
| - name: Setup Node.js ${{ matrix.node-version }} | ||
| uses: actions/setup-node@60edb5dd545a775178fac7f3a11ecda6e5a4f69f # v4.0.2 | ||
| with: | ||
| node-version: ${{ matrix.node-version }} | ||
| cache: npm | ||
| - name: Install dependencies | ||
| run: npm ci | ||
| - name: Run linter | ||
| run: npm run lint --if-present | ||
| - name: Run tests | ||
| run: npm test --if-present | ||
| - name: Generate coverage report | ||
| run: npm run coverage --if-present | ||
| continue-on-error: true | ||
| - name: Upload coverage to Codecov | ||
| uses: codecov/codecov-action@125fc84a3e5e4183e5e9c34b23b9ef1d16cbf484 # v3.1.6 | ||
| if: always() | ||
| with: | ||
| files: ./coverage/coverage-final.json | ||
| fail_ci_if_error: false | ||
| security-scan: | ||
| name: Security Scan | ||
| runs-on: ubuntu-22.04 | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 | ||
| - name: Run Trivy vulnerability scanner | ||
| uses: aquasecurity/trivy-action@6e7b7d1fd3e4692731fcf9cdff0f8244cfad8103 # v0.24.0 | ||
| with: | ||
| scan-type: fs | ||
| scan-ref: . | ||
| format: sarif | ||
| output: trivy-results.sarif | ||
| - name: Upload Trivy results to GitHub Security tab | ||
| uses: github/codeql-action/upload-sarif@cf7e9f23492505046de19cd2d8569798fc6f4eac # v3.25.4 | ||
| with: | ||
| sarif_file: trivy-results.sarif | ||
| build-image: | ||
| name: Build and Push Docker Image | ||
| runs-on: ubuntu-22.04 | ||
| needs: [lint-test, security-scan] | ||
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') | ||
| permissions: | ||
| id-token: write | ||
| contents: read | ||
| outputs: | ||
| image-uri: ${{ steps.image.outputs.image-uri }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 | ||
| - name: Configure AWS credentials via OIDC | ||
| uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e93febb1 # v4.0.2 | ||
| with: | ||
| role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} | ||
| aws-region: ${{ env.AWS_REGION }} | ||
| - name: Login to Amazon ECR | ||
| id: login-ecr | ||
| uses: aws-actions/amazon-ecr-login@062b18b96a7aff0 # v2.0.1 | ||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16eca30d26365 # v3.0.0 | ||
| - name: Build and push Docker image | ||
| id: docker-build | ||
| uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 | ||
| with: | ||
| context: . | ||
| push: true | ||
| tags: | | ||
| ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }} | ||
| ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||
| build-args: | | ||
| BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') | ||
| VCS_REF=${{ github.sha }} | ||
| - name: Output image URI | ||
| id: image | ||
| run: | | ||
| echo "image-uri=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}" >> $GITHUB_OUTPUT | ||
| terraform-plan: | ||
| name: Terraform Plan | ||
| runs-on: ubuntu-22.04 | ||
| needs: build-image | ||
| if: github.event_name == 'push' && github.ref == 'refs/heads/develop' | ||
| permissions: | ||
| id-token: write | ||
| contents: read | ||
| pull-requests: write | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 | ||
| - name: Configure AWS credentials via OIDC | ||
| uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e93febb1 # v4.0.2 | ||
| with: | ||
| role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} | ||
| aws-region: ${{ env.AWS_REGION }} | ||
| - name: Setup Terraform | ||
| uses: hashicorp/setup-terraform@v2.0.3 | ||
| with: | ||
| terraform_version: 1.7.0 | ||
| - name: Terraform Format Check | ||
| run: terraform fmt -check -recursive ./terraform | ||
| - name: Terraform Init | ||
| run: cd terraform && terraform init -backend-config="bucket=${{ secrets.TERRAFORM_STATE_BUCKET }}" -backend-config="key=prod/terraform.tfstate" -backend-config="region=${{ env.AWS_REGION }}" | ||
| - name: Terraform Validate | ||
| run: cd terraform && terraform validate | ||
| - name: Terraform Plan | ||
| id: plan | ||
| run: | | ||
| cd terraform && terraform plan \ | ||
| -var="image_uri=${{ needs.build-image.outputs.image-uri }}" \ | ||
| -var="environment=staging" \ | ||
| -out=tfplan | ||
| continue-on-error: true | ||
| - name: Comment Terraform Plan on PR | ||
| if: github.event_name == 'pull_request' | ||
| uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | ||
| with: | ||
| script: | | ||
| const fs = require('fs'); | ||
| const plan = fs.readFileSync('terraform/tfplan', 'utf8'); | ||
| github.rest.issues.createComment({ | ||
| issue_number: context.issue.number, | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| body: `## Terraform Plan\n\`\`\`\n${plan}\n\`\`\`` | ||
| }); | ||
| deploy-staging: | ||
| name: Deploy to Staging | ||
| runs-on: ubuntu-22.04 | ||
| needs: [build-image, terraform-plan] | ||
| if: github.event_name == ' | ||