|
| 1 | +version: 2.1 |
| 2 | + |
| 3 | + |
| 4 | +orbs: |
| 5 | + |
| 6 | + |
| 7 | + aws-cli: circleci/[email protected] |
| 8 | + ggshield: gitguardian/[email protected] |
| 9 | + |
| 10 | + |
| 11 | +parameters: |
| 12 | + aws-account-id: |
| 13 | + type: string |
| 14 | + default: CHANGE_ME |
| 15 | + aws-role-arn: |
| 16 | + type: string |
| 17 | + default: CHANGE_ME |
| 18 | + working-dir: |
| 19 | + type: string |
| 20 | + default: ~/aws-deployment-pipeline-reference-architecture/examples/circleci-application-pipeline |
| 21 | + |
| 22 | + |
| 23 | +commands: |
| 24 | + install-cdk: |
| 25 | + parameters: |
| 26 | + version: |
| 27 | + type: string |
| 28 | + default: latest |
| 29 | + cdk-lib: |
| 30 | + type: boolean |
| 31 | + default: true |
| 32 | + steps: |
| 33 | + - run: |
| 34 | + name: "Install AWS CDK" |
| 35 | + command: sudo npm install -g aws-cdk@<< parameters.version >> |
| 36 | + - when: |
| 37 | + condition: |
| 38 | + and: |
| 39 | + - equal: [ true, << parameters.cdk-lib >> ] |
| 40 | + steps: |
| 41 | + - run: |
| 42 | + name: "Installing AWS CDK Lib" |
| 43 | + command: sudo npm install aws-cdk-lib |
| 44 | + |
| 45 | + |
| 46 | +jobs: |
| 47 | + synth: |
| 48 | + docker: |
| 49 | + - image: cimg/node:23.1.0 |
| 50 | + working_directory: << pipeline.parameters.working-dir >> |
| 51 | + steps: |
| 52 | + - checkout: |
| 53 | + path: ~/aws-deployment-pipeline-reference-architecture |
| 54 | + - node/install-packages: |
| 55 | + with-cache: true |
| 56 | + cache-path: << pipeline.parameters.working-dir >>/node_modules |
| 57 | + - run: |
| 58 | + name: Audit and Fix Dependencies |
| 59 | + command: | |
| 60 | + npm audit || true # Log vulnerabilities but don't fail the build |
| 61 | + npm audit fix # Attempt to fix vulnerabilities |
| 62 | + - run: |
| 63 | + name: Run Test |
| 64 | + command: npm test |
| 65 | + - run: |
| 66 | + name: Lint Code |
| 67 | + command: npm run lint |
| 68 | + - run: |
| 69 | + name: Build Project |
| 70 | + command: npm run build |
| 71 | + - store_test_results: |
| 72 | + path: << pipeline.parameters.working-dir >>/test-reports |
| 73 | + - store_artifacts: |
| 74 | + path: << pipeline.parameters.working-dir >>/test-reports |
| 75 | + |
| 76 | + trivy: |
| 77 | + docker: |
| 78 | + - image: cimg/base:2024.11 |
| 79 | + working_directory: << pipeline.parameters.working-dir >> |
| 80 | + steps: |
| 81 | + - checkout: |
| 82 | + path: ~/aws-deployment-pipeline-reference-architecture |
| 83 | + - trivy/scan: |
| 84 | + scan-type: fs |
| 85 | + ignore-unfixed: true |
| 86 | + format: sarif |
| 87 | + output: << pipeline.parameters.working-dir >>/report.sarif |
| 88 | + scanners: vuln,secret,misconfig,license |
| 89 | + - store_artifacts: |
| 90 | + path: << pipeline.parameters.working-dir >>/report.sarif |
| 91 | + environment: |
| 92 | + TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db |
| 93 | + |
| 94 | + package: |
| 95 | + docker: |
| 96 | + - image: cimg/openjdk:17.0 |
| 97 | + working_directory: << pipeline.parameters.working-dir >> |
| 98 | + environment: |
| 99 | + TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db |
| 100 | + steps: |
| 101 | + - checkout: |
| 102 | + path: ~/aws-deployment-pipeline-reference-architecture |
| 103 | + - restore_cache: |
| 104 | + keys: |
| 105 | + - maven-repo-v1-{{ checksum "pom.xml" }} |
| 106 | + - run: |
| 107 | + name: Run Maven Verify |
| 108 | + command: mvn verify --batch-mode --no-transfer-progress |
| 109 | + - save_cache: |
| 110 | + paths: |
| 111 | + - ~/.m2/repository |
| 112 | + key: maven-repo-v1-{{ checksum "pom.xml" }} |
| 113 | + - trivy/scan: |
| 114 | + scan-type: fs |
| 115 | + ignore-unfixed: true |
| 116 | + format: spdx-json |
| 117 | + output: << pipeline.parameters.working-dir >>/dependency-results.sbom.json |
| 118 | + - store_test_results: |
| 119 | + path: << pipeline.parameters.working-dir >>/target/surefire-reports |
| 120 | + - store_test_results: |
| 121 | + path: << pipeline.parameters.working-dir >>/target/soapui-reports |
| 122 | + - store_artifacts: |
| 123 | + path: << pipeline.parameters.working-dir >>/dependency-results.sbom.json |
| 124 | + - store_artifacts: |
| 125 | + path: << pipeline.parameters.working-dir >>/target/spotbugsXml.xml |
| 126 | + - store_artifacts: |
| 127 | + path: << pipeline.parameters.working-dir >>/target/jmeter/results |
| 128 | + - store_artifacts: |
| 129 | + path: << pipeline.parameters.working-dir >>/target/fruit-api.jar |
| 130 | + - persist_to_workspace: |
| 131 | + root: << pipeline.parameters.working-dir >> |
| 132 | + paths: |
| 133 | + - target/fruit-api.jar |
| 134 | + |
| 135 | + deploy: |
| 136 | + docker: |
| 137 | + - image: cimg/aws:2024.03 |
| 138 | + parameters: |
| 139 | + environment: |
| 140 | + type: string |
| 141 | + default: Beta |
| 142 | + stack-name: |
| 143 | + type: string |
| 144 | + default: fruit-api |
| 145 | + region: |
| 146 | + type: string |
| 147 | + default: us-east-1 |
| 148 | + cdk-context: |
| 149 | + type: string |
| 150 | + default: deploymentConfigurationName=CodeDeployDefault.ECSCanary10Percent5Minutes |
| 151 | + working_directory: << pipeline.parameters.working-dir >> |
| 152 | + steps: |
| 153 | + - checkout: |
| 154 | + path: ~/aws-deployment-pipeline-reference-architecture |
| 155 | + - attach_workspace: |
| 156 | + at: << pipeline.parameters.working-dir >> |
| 157 | + - setup_remote_docker: |
| 158 | + docker_layer_caching: true |
| 159 | + - aws-cli/setup: |
| 160 | + profile_name: default |
| 161 | + role_arn: << pipeline.parameters.aws-role-arn >> |
| 162 | + role_session_name: default |
| 163 | + - install-cdk |
| 164 | + - run: |
| 165 | + name: Set CDK Env Vars |
| 166 | + command: | |
| 167 | + echo "export CDK_DEPLOY_ACCOUNT=<< pipeline.parameters.aws-account-id >>" >> $BASH_ENV |
| 168 | + echo "export CDK_DEPLOY_REGION=<< parameters.region >>" >> $BASH_ENV |
| 169 | + - run: |
| 170 | + name: Bootstrap CDK Environment |
| 171 | + command: cdk bootstrap aws://$CDK_DEPLOY_ACCOUNT/$CDK_DEPLOY_REGION |
| 172 | + - run: |
| 173 | + name: Deploy CDK Stack << parameters.stack-name >> |
| 174 | + command: | |
| 175 | + cdk deploy << parameters.stack-name >> \ |
| 176 | + --outputs-file << parameters.environment >>-<< parameters.region >>-cdk-output.json \ |
| 177 | + --context << parameters.cdk-context >> \ |
| 178 | + --require-approval never |
| 179 | + no_output_timeout: 20m |
| 180 | + - run: |
| 181 | + name: Track Release in CircleCI |
| 182 | + command: circleci run release log --environment-name=<< parameters.environment >> --component-name=<< parameters.stack-name >> --target-version=<< parameters.region >>-${CIRCLE_BUILD_NUM} |
| 183 | + - store_artifacts: |
| 184 | + path: << pipeline.parameters.working-dir >>/<< parameters.environment >>-<< parameters.region >>-cdk-output.json |
| 185 | + - persist_to_workspace: |
| 186 | + root: << pipeline.parameters.working-dir >> |
| 187 | + paths: |
| 188 | + - << parameters.environment >>-<< parameters.region >>-cdk-output.json |
| 189 | + |
| 190 | + test: |
| 191 | + docker: |
| 192 | + - image: cimg/openjdk:17.0 |
| 193 | + parameters: |
| 194 | + environment: |
| 195 | + type: string |
| 196 | + default: Beta |
| 197 | + region: |
| 198 | + type: string |
| 199 | + default: us-east-1 |
| 200 | + threads: |
| 201 | + type: integer |
| 202 | + default: 300 |
| 203 | + duration: |
| 204 | + type: integer |
| 205 | + default: 300 |
| 206 | + throughput: |
| 207 | + type: integer |
| 208 | + default: 6000 |
| 209 | + working_directory: << pipeline.parameters.working-dir >> |
| 210 | + steps: |
| 211 | + - checkout: |
| 212 | + path: ~/aws-deployment-pipeline-reference-architecture |
| 213 | + - attach_workspace: |
| 214 | + at: << pipeline.parameters.working-dir >> |
| 215 | + - run: |
| 216 | + name: Extract endpointUrl from CDK Output |
| 217 | + command: | |
| 218 | + # Extract the endpointUrl from the CDK output JSON |
| 219 | + if [ -f << parameters.environment >>-<< parameters.region >>-cdk-output.json ]; then |
| 220 | + endpoint_url=$(jq -r '.["fruit-api"].endpointUrl' << parameters.environment >>-<< parameters.region >>-cdk-output.json) |
| 221 | + echo "export ENDPOINT_URL=$endpoint_url" >> $BASH_ENV |
| 222 | + echo "Endpoint URL extracted: $endpoint_url" |
| 223 | + else |
| 224 | + echo "CDK output file not found." |
| 225 | + exit 1 |
| 226 | + fi |
| 227 | + - restore_cache: |
| 228 | + keys: |
| 229 | + - maven-repo-v1-{{ checksum "pom.xml" }} |
| 230 | + - run: |
| 231 | + name: Run SoapUI Tests against << parameters.environment >> |
| 232 | + command: mvn --batch-mode --no-transfer-progress soapui:test -Dsoapui.endpoint=${ENDPOINT_URL} |
| 233 | + - run: |
| 234 | + name: Run JMeter Tests against << parameters.environment >> |
| 235 | + command: mvn --batch-mode --no-transfer-progress compile jmeter:jmeter jmeter:results -Djmeter.endpoint=${ENDPOINT_URL} -Djmeter.threads=<< parameters.threads >> -Djmeter.duration=<< parameters.duration >> -Djmeter.throughput=<< parameters.throughput >> |
| 236 | + - save_cache: |
| 237 | + paths: |
| 238 | + - ~/.m2/repository |
| 239 | + key: maven-repo-v1-{{ checksum "pom.xml" }} |
| 240 | + - store_test_results: |
| 241 | + path: << pipeline.parameters.working-dir >>/target/soapui-reports |
| 242 | + - store_artifacts: |
| 243 | + path: << pipeline.parameters.working-dir >>/target/jmeter/results |
| 244 | + |
| 245 | + check-pr: |
| 246 | + docker: |
| 247 | + - image: cimg/base:current-22.04 |
| 248 | + resource_class: small |
| 249 | + environment: |
| 250 | + WEBHOOK_BODY: << pipeline.trigger_parameters.webhook.body >> |
| 251 | + steps: |
| 252 | + - run: |
| 253 | + name: Check PR Event Type |
| 254 | + command: | |
| 255 | + echo "Received WEBHOOK_BODY: $WEBHOOK_BODY" |
| 256 | +
|
| 257 | + # Parse the 'action' from the GitHub webhook body |
| 258 | + PR_ACTION=$(echo "$WEBHOOK_BODY" | jq -r '.action') |
| 259 | +
|
| 260 | + # Only continue if the action is 'opened', 'reopened', or 'synchronize' |
| 261 | + if [[ "$PR_ACTION" == "opened" || "$PR_ACTION" == "reopened" ]]; then |
| 262 | + echo "PR action is $PR_ACTION. Proceeding with the pipeline." |
| 263 | + else |
| 264 | + echo "Event action '$PR_ACTION' does not match required events (opened or reopened). Exiting job." |
| 265 | + curl -X POST https://circleci.com/api/v1.1/project/circleci/${ORG_SLUG}/${PROJECT_SLUG}/${CIRCLE_BUILD_NUM}/cancel -H "Circle-Token: ${CANCEL_JOB}" |
| 266 | + fi |
| 267 | +
|
| 268 | +
|
| 269 | +workflows: |
| 270 | + pr_pipeline: |
| 271 | + when: |
| 272 | + and: |
| 273 | + - equal: ["webhook", "<< pipeline.trigger_parameters.circleci.trigger_type >>"] |
| 274 | + jobs: |
| 275 | + - check-pr: |
| 276 | + name: Checking PR Event |
| 277 | + context: dpra-cancel |
| 278 | + - ggshield/scan: |
| 279 | + name: Scanning for Secrets with GitGuardian |
| 280 | + revision: <<pipeline.git.revision>> |
| 281 | + context: dpra-gitguardian |
| 282 | + requires: |
| 283 | + - Checking PR Event |
| 284 | + - synth: |
| 285 | + name: Verify CDK Synth |
| 286 | + requires: |
| 287 | + - Checking PR Event |
| 288 | + - trivy: |
| 289 | + name: Run Trivy Scan |
| 290 | + requires: |
| 291 | + - Checking PR Event |
| 292 | + - package: |
| 293 | + name: Build Application |
| 294 | + requires: |
| 295 | + - Checking PR Event |
| 296 | + |
| 297 | + deployment_pipeline: |
| 298 | + when: |
| 299 | + and: |
| 300 | + - equal: ["github_app", "<< pipeline.trigger_parameters.circleci.trigger_type >>"] |
| 301 | + jobs: |
| 302 | + - ggshield/scan: |
| 303 | + name: Scanning for Secrets with GitGuardian |
| 304 | + revision: <<pipeline.git.revision>> |
| 305 | + context: dpra-gitguardian |
| 306 | + - synth: |
| 307 | + name: Verify CDK Synth |
| 308 | + - trivy: |
| 309 | + name: Run Trivy Scan |
| 310 | + - package: |
| 311 | + name: Build Application |
| 312 | + - deploy: |
| 313 | + name: Beta Deploy |
| 314 | + requires: |
| 315 | + - Verify CDK Synth |
| 316 | + - Run Trivy Scan |
| 317 | + - Build Application |
| 318 | + - Scanning for Secrets with GitGuardian |
| 319 | + - test: |
| 320 | + name: Beta Test |
| 321 | + environment: Beta |
| 322 | + requires: |
| 323 | + - "Beta Deploy" |
| 324 | + - deploy: |
| 325 | + name: "<< matrix.environment >> << matrix.region>> Deploy" |
| 326 | + matrix: |
| 327 | + parameters: |
| 328 | + environment: [Gamma] |
| 329 | + region: [us-east-1, us-west-2] |
| 330 | + requires: |
| 331 | + - "Beta Test" |
| 332 | + filters: |
| 333 | + branches: |
| 334 | + only: |
| 335 | + - main |
| 336 | + - test: |
| 337 | + name: "<< matrix.environment >> << matrix.region>> Test" |
| 338 | + matrix: |
| 339 | + parameters: |
| 340 | + environment: [Gamma] |
| 341 | + region: [us-east-1, us-west-2] |
| 342 | + requires: |
| 343 | + - << matrix.environment >> << matrix.region>> Deploy |
| 344 | + filters: |
| 345 | + branches: |
| 346 | + only: |
| 347 | + - main |
| 348 | + - hold: |
| 349 | + type: approval |
| 350 | + name: Approval for Production Deploy |
| 351 | + requires: |
| 352 | + - "Gamma us-east-1 Test" |
| 353 | + - "Gamma us-west-2 Test" |
| 354 | + filters: |
| 355 | + branches: |
| 356 | + only: |
| 357 | + - main |
| 358 | + - deploy: |
| 359 | + name: "<< matrix.environment >> << matrix.region>> Deploy" |
| 360 | + matrix: |
| 361 | + parameters: |
| 362 | + environment: [Production] |
| 363 | + region: [us-east-1, us-west-2] |
| 364 | + requires: |
| 365 | + - "Approval for Production Deploy" |
| 366 | + filters: |
| 367 | + branches: |
| 368 | + only: |
| 369 | + - main |
| 370 | + - test: |
| 371 | + name: "<< matrix.environment >> << matrix.region>> Test" |
| 372 | + matrix: |
| 373 | + parameters: |
| 374 | + environment: [Production] |
| 375 | + region: [us-east-1, us-west-2] |
| 376 | + requires: |
| 377 | + - << matrix.environment >> << matrix.region>> Deploy |
| 378 | + filters: |
| 379 | + branches: |
| 380 | + only: |
| 381 | + - main |
0 commit comments