diff --git a/.agents/onboard.md b/.agents/onboard.md index 3abc130c2..5daac3c0b 100644 --- a/.agents/onboard.md +++ b/.agents/onboard.md @@ -14,7 +14,7 @@ read scripts/bootcamp.sh to learn how to test services `make start` to start services in docker. services use `cargo-watch` for hot-reloading during development -test the bootcamp commands to learn services requests and responses +test the bootcamp commands to learn services requests and responses. the primary transaction bootcamp commands are `make rule`, `make request-create`, `make request-approve` and `make balance-by-account` project.yaml is project config uniformly sourced in bash, make and terraform code to avoid scattering it across the project. its large so parse when possible. for example, `yq .services.rule.env_var.set project.yaml` to list environment variables set by services/rule and `yq .services.rule.env_var.get project.yaml` to list variables it requires @@ -102,4 +102,16 @@ check cloudwatch logs: `aws logs tail /aws/lambda/SERVICE-ENVID-ENV --since 5m - image tags use `SHORT_GIT_SHA_LENGTH` from project.yaml (default: 7) for git hash length -use yq instead of jq for local json/yaml scripting \ No newline at end of file +use yq instead of jq for local json/yaml scripting + +`bash scripts/ecr-images.sh --build` triggers codebuild to build+test images remotely. add `--push` to push to ECR, `--deploy` to update lambdas, `--no-test` to skip tests, `--service graphql` to target one service + +`bash scripts/ecr-images.sh --integ` runs integration tests in codebuild using pre-built ECR images (test-db, test-cache, test-local, client e2e). requires `--build --push` first + +`bash scripts/ecr-images.sh --pull` pulls images from ECR and retags locally + +codebuild projects are in infra/terraform/aws/modules/project-storage/v001. per-service builds in codepipeline.tf (sources codebuild module), integ tests in integ.tf (buildspec inlined) + +buildspecs use runtime config via env vars (RUN_TESTS, PUSH_IMAGE, DEPLOY) set by `--environment-variables-override` in ecr-images.sh + +s3 upload to artifacts bucket auto-triggers codepipeline via eventbridge when using `--build --push` without `--service` \ No newline at end of file diff --git a/.github/workflows/REUSE_service.yaml b/.github/workflows/REUSE_service.yaml deleted file mode 100644 index 55c37abd4..000000000 --- a/.github/workflows/REUSE_service.yaml +++ /dev/null @@ -1,154 +0,0 @@ -name: REUSE_service - -on: - workflow_call: - inputs: - app_dir: - required: true - type: string - secrets: - AWS_ACCESS_KEY_ID: - required: true - AWS_SECRET_ACCESS_KEY: - required: true - AWS_ACCOUNT_ID: - required: true - DEV_ENV_ID: - required: true - -jobs: - lint_test: - name: lint test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: clippy, rustfmt - - uses: Swatinem/rust-cache@v2 - - name: linting - run: | - cargo fmt -- --check - cargo clippy -- -Dwarnings - - unit_test: - name: unit test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: clippy, rustfmt - - uses: Swatinem/rust-cache@v2 - - name: unit test - run: cargo test - - database_test: - name: database test in local docker - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: clippy, rustfmt - - uses: Swatinem/rust-cache@v2 - - name: test database - run: make -C crates/pg test-db - - compile: - name: compile ${{ matrix.service }} - runs-on: ubuntu-latest - strategy: - matrix: - service: - - graphql - - request-create - - request-approve - - rule - - request-by-id - - requests-by-account - - transaction-by-id - - transactions-by-account - - balance-by-account - # TODO: - # - event - # - measure - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - - uses: Swatinem/rust-cache@v2 - with: - shared-key: ${{ matrix.service }} - - name: compile - run: cargo build -p ${{ matrix.service }} - - name: upload binary - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.service }} - path: target/debug/${{ matrix.service }} - retention-days: 1 - - integration_test: - name: integration test in local docker - needs: compile - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: download all binaries - uses: actions/download-artifact@v4 - with: - path: target/debug/ - merge-multiple: true - - name: set permissions - run: chmod +x target/debug/* - - name: start services - run: make start - - name: test service integration - run: make -C ./tests test-local - - name: clean up - run: make stop - - client_test: - name: client test in local docker - needs: compile - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: download all binaries - uses: actions/download-artifact@v4 - with: - path: target/debug/ - merge-multiple: true - - name: set permissions - run: chmod +x target/debug/* - - name: start services - run: make start - - name: e2e test client - run: make -C ./client test-ci - - name: clean up - run: make stop - - push_image: - name: push image to dev ecr - runs-on: ubuntu-latest - needs: [lint_test, unit_test, database_test, integration_test, client_test] - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: us-east-1 - APP_DIR: ${{ inputs.app_dir }} - steps: - - uses: actions/checkout@v4 - - name: mask values - run: echo "::add-mask::${{ secrets.AWS_ACCOUNT_ID }}" - - name: build image - run: make -C $APP_DIR build-image - - name: tag image - run: ENV_ID=${{ secrets.DEV_ENV_ID }} make -C $APP_DIR tag-dev-image - - name: push image - run: ENV_ID=${{ secrets.DEV_ENV_ID }} make -C $APP_DIR push-dev-image diff --git a/.github/workflows/balance-by-account.yaml b/.github/workflows/balance-by-account.yaml deleted file mode 100644 index 113e156bc..000000000 --- a/.github/workflows/balance-by-account.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: balance-by-account - -on: - workflow_dispatch: - push: - paths: - - 'services/balance-by-account/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/balance-by-account - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/build-all-images.yaml b/.github/workflows/build-all-images.yaml deleted file mode 100644 index e581dcb13..000000000 --- a/.github/workflows/build-all-images.yaml +++ /dev/null @@ -1,331 +0,0 @@ -name: build-all-images - -on: - workflow_dispatch: - -env: - ENV_ID: ${{ secrets.DEV_ENV_ID }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - GITHUB_REGISTRY: ghcr.io - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - rule: - name: rule - runs-on: ubuntu-latest - env: - SERVICE_NAME: rule - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - balance_by_account: - name: balance-by-account - runs-on: ubuntu-latest - env: - SERVICE_NAME: balance-by-account - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - graphql: - name: graphql - runs-on: ubuntu-latest - env: - SERVICE_NAME: graphql - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - request_create: - name: request-create - runs-on: ubuntu-latest - env: - SERVICE_NAME: request-create - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - request_approve: - name: request-approve - runs-on: ubuntu-latest - env: - SERVICE_NAME: request-approve - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - request_by_id: - name: request-by-id - runs-on: ubuntu-latest - env: - SERVICE_NAME: request-by-id - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - requests_by_account: - name: requests-by-account - runs-on: ubuntu-latest - env: - SERVICE_NAME: requests-by-account - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - transaction_by_id: - name: transaction-by-id - runs-on: ubuntu-latest - env: - SERVICE_NAME: transaction-by-id - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - transactions_by_account: - name: transactions-by-account - runs-on: ubuntu-latest - env: - SERVICE_NAME: transactions-by-account - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - event: - name: event - runs-on: ubuntu-latest - env: - SERVICE_NAME: event - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - measure: - name: measure - runs-on: ubuntu-latest - env: - SERVICE_NAME: measure - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - auto_confirm: - name: auto-confirm - runs-on: ubuntu-latest - env: - SERVICE_NAME: auto-confirm - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - go_migrate: - name: go-migrate - runs-on: ubuntu-latest - env: - SERVICE_NAME: go-migrate - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx ./migrations/go-migrate - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - warm_cache: - name: warm-cache - runs-on: ubuntu-latest - env: - SERVICE_NAME: warm-cache - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME - client: - name: client - runs-on: ubuntu-latest - env: - SERVICE_NAME: client - steps: - - uses: actions/checkout@v4 - - name: build image - run: bash scripts/build-image-job.sh --service-name $SERVICE_NAME --build-ctx . - - name: tag image with current short sha and latest - run: | - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:${GITHUB_SHA:0:7} - docker tag $SERVICE_NAME:latest ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME:latest - - name: log into container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.GITHUB_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: push images - run: docker push --all-tags ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}/$SERVICE_NAME \ No newline at end of file diff --git a/.github/workflows/deploy-all-images.yaml b/.github/workflows/deploy-all-images.yaml deleted file mode 100644 index a039eba27..000000000 --- a/.github/workflows/deploy-all-images.yaml +++ /dev/null @@ -1,124 +0,0 @@ -name: deploy-all-images - -on: - workflow_dispatch: - -env: - ENV_ID: ${{ secrets.DEV_ENV_ID }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: us-east-1 - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - rule: - name: rule - runs-on: ubuntu-latest - env: - SERVICE_NAME: rule - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - balance_by_account: - name: balance-by-account - runs-on: ubuntu-latest - env: - SERVICE_NAME: balance-by-account - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - graphql: - name: graphql - runs-on: ubuntu-latest - env: - SERVICE_NAME: graphql - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - request_create: - name: request-create - runs-on: ubuntu-latest - env: - SERVICE_NAME: request-create - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - request_approve: - name: request-approve - runs-on: ubuntu-latest - env: - SERVICE_NAME: request-approve - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - request_by_id: - name: request-by-id - runs-on: ubuntu-latest - env: - SERVICE_NAME: request-by-id - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - requests_by_account: - name: requests-by-account - runs-on: ubuntu-latest - env: - SERVICE_NAME: requests-by-account - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - transaction_by_id: - name: transaction-by-id - runs-on: ubuntu-latest - env: - SERVICE_NAME: transaction-by-id - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - transactions_by_account: - name: transactions-by-account - runs-on: ubuntu-latest - env: - SERVICE_NAME: transactions-by-account - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - auto_confirm: - name: auto-confirm - runs-on: ubuntu-latest - env: - SERVICE_NAME: auto-confirm - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - go_migrate: - name: go-migrate - runs-on: ubuntu-latest - env: - SERVICE_NAME: go-migrate - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME - warm_cache: - name: warm-cache - runs-on: ubuntu-latest - env: - SERVICE_NAME: warm-cache - steps: - - uses: actions/checkout@v4 - - name: build and deploy image - run: bash scripts/deploy-image-job.sh --service-name $SERVICE_NAME \ No newline at end of file diff --git a/.github/workflows/dev-integration.yaml b/.github/workflows/dev-integration.yaml index 53e4aa7e9..372f1c976 100644 --- a/.github/workflows/dev-integration.yaml +++ b/.github/workflows/dev-integration.yaml @@ -49,7 +49,7 @@ jobs: - name: warm up lambdas with availability script run: bash scripts/test-availability.sh - name: reset dev rds - run: ENV_ID=${{ secrets.DEV_ENV_ID }} make --no-print-directory -C ./migrations resetrds ENV=dev DB=test + run: ENV_ID=${{ secrets.DEV_ENV_ID }} make --no-print-directory -C ./migrations/go-migrate resetrds ENV=dev DB=test - name: warm cache run: ENV_ID=${{ secrets.DEV_ENV_ID }} bash scripts/invoke-warm-cache.sh --env dev - name: run dev cloud integration tests diff --git a/.github/workflows/graphql.yaml b/.github/workflows/graphql.yaml deleted file mode 100644 index 8fb34a146..000000000 --- a/.github/workflows/graphql.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: graphql - -on: - workflow_dispatch: - push: - paths: - - 'services/graphql/**' - - 'crates/**' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/graphql - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/mirror-images.yaml b/.github/workflows/mirror-images.yaml new file mode 100644 index 000000000..377d88c17 --- /dev/null +++ b/.github/workflows/mirror-images.yaml @@ -0,0 +1,50 @@ +name: mirror-images + +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' # weekly + +jobs: + mirror: + name: mirror base images to ghcr + runs-on: ubuntu-latest + permissions: + packages: write + steps: + - name: login to ghcr + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: mirror rust + run: | + docker pull public.ecr.aws/docker/library/rust:latest + docker tag public.ecr.aws/docker/library/rust:latest ghcr.io/${{ github.repository_owner }}/rust:latest + docker push ghcr.io/${{ github.repository_owner }}/rust:latest + - name: mirror lambda-provided + run: | + docker pull public.ecr.aws/lambda/provided:al2023 + docker tag public.ecr.aws/lambda/provided:al2023 ghcr.io/${{ github.repository_owner }}/lambda-provided:al2023 + docker push ghcr.io/${{ github.repository_owner }}/lambda-provided:al2023 + - name: mirror postgresql + run: | + docker pull public.ecr.aws/bitnami/postgresql:15 + docker tag public.ecr.aws/bitnami/postgresql:15 ghcr.io/${{ github.repository_owner }}/postgresql:15 + docker push ghcr.io/${{ github.repository_owner }}/postgresql:15 + - name: mirror redis + run: | + docker pull public.ecr.aws/bitnami/redis:latest + docker tag public.ecr.aws/bitnami/redis:latest ghcr.io/${{ github.repository_owner }}/redis:latest + docker push ghcr.io/${{ github.repository_owner }}/redis:latest + - name: mirror alpine + run: | + docker pull public.ecr.aws/docker/library/alpine:latest + docker tag public.ecr.aws/docker/library/alpine:latest ghcr.io/${{ github.repository_owner }}/alpine:latest + docker push ghcr.io/${{ github.repository_owner }}/alpine:latest + - name: mirror node + run: | + docker pull public.ecr.aws/docker/library/node:lts-alpine + docker tag public.ecr.aws/docker/library/node:lts-alpine ghcr.io/${{ github.repository_owner }}/node:lts-alpine + docker push ghcr.io/${{ github.repository_owner }}/node:lts-alpine diff --git a/.github/workflows/request-approve.yaml b/.github/workflows/request-approve.yaml deleted file mode 100644 index 7e449f2dc..000000000 --- a/.github/workflows/request-approve.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: request-approve - -on: - workflow_dispatch: - push: - paths: - - 'services/request-approve/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/request-approve - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/request-by-id.yaml b/.github/workflows/request-by-id.yaml deleted file mode 100644 index 780e9db9f..000000000 --- a/.github/workflows/request-by-id.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: request-by-id - -on: - workflow_dispatch: - push: - paths: - - 'services/request-by-id/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/request-by-id - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/request-create.yaml b/.github/workflows/request-create.yaml deleted file mode 100644 index b85ca3e20..000000000 --- a/.github/workflows/request-create.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: request-create - -on: - workflow_dispatch: - push: - paths: - - 'services/request-create/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/request-create - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/requests-by-account.yaml b/.github/workflows/requests-by-account.yaml deleted file mode 100644 index e2048e16e..000000000 --- a/.github/workflows/requests-by-account.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: requests-by-account - -on: - workflow_dispatch: - push: - paths: - - 'services/requests-by-account/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/requests-by-account - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/rule.yaml b/.github/workflows/rule.yaml deleted file mode 100644 index 6d105cf33..000000000 --- a/.github/workflows/rule.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: rule - -on: - workflow_dispatch: - push: - paths: - - 'services/rule/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/rule - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/services.yaml b/.github/workflows/services.yaml new file mode 100644 index 000000000..4920d83da --- /dev/null +++ b/.github/workflows/services.yaml @@ -0,0 +1,245 @@ +name: services + +on: + workflow_dispatch: + push: + paths: + - 'services/graphql/**' + - 'services/request-create/**' + - 'services/request-approve/**' + - 'services/rule/**' + - 'services/request-by-id/**' + - 'services/requests-by-account/**' + - 'services/transaction-by-id/**' + - 'services/transactions-by-account/**' + - 'services/balance-by-account/**' + - 'crates/**' + - 'migrations/schema/*' + branches-ignore: + - 'master' + - 'develop' + +concurrency: + group: services-${{ github.ref }} + cancel-in-progress: true + +jobs: + cache_images: + name: cache base images + runs-on: ubuntu-latest + permissions: + packages: read + steps: + - name: login to ghcr + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: restore image cache + id: cache + uses: actions/cache@v4 + with: + path: ~/image-cache + key: base-images-v1 + - name: pull and retag images + if: steps.cache.outputs.cache-hit != 'true' + run: | + mkdir -p ~/image-cache + docker pull ghcr.io/systemaccounting/rust:latest + docker tag ghcr.io/systemaccounting/rust:latest public.ecr.aws/docker/library/rust:latest + docker pull ghcr.io/systemaccounting/lambda-provided:al2023 + docker tag ghcr.io/systemaccounting/lambda-provided:al2023 public.ecr.aws/lambda/provided:al2023 + docker pull ghcr.io/systemaccounting/postgresql:15 + docker tag ghcr.io/systemaccounting/postgresql:15 public.ecr.aws/bitnami/postgresql:15 + docker pull ghcr.io/systemaccounting/redis:latest + docker tag ghcr.io/systemaccounting/redis:latest public.ecr.aws/bitnami/redis:latest + docker pull ghcr.io/systemaccounting/alpine:latest + docker tag ghcr.io/systemaccounting/alpine:latest public.ecr.aws/docker/library/alpine:latest + docker pull ghcr.io/systemaccounting/node:lts-alpine + docker tag ghcr.io/systemaccounting/node:lts-alpine public.ecr.aws/docker/library/node:lts-alpine + docker save -o ~/image-cache/images.tar \ + public.ecr.aws/docker/library/rust:latest \ + public.ecr.aws/lambda/provided:al2023 \ + public.ecr.aws/bitnami/postgresql:15 \ + public.ecr.aws/bitnami/redis:latest \ + public.ecr.aws/docker/library/alpine:latest \ + public.ecr.aws/docker/library/node:lts-alpine + + lint_test: + name: lint test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: clippy, rustfmt + - uses: Swatinem/rust-cache@v2 + - name: linting + run: | + cargo fmt -- --check + cargo clippy -- -Dwarnings + + unit_test: + name: unit test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: clippy, rustfmt + - uses: Swatinem/rust-cache@v2 + - name: unit test + run: cargo test + + database_test: + name: database test in local docker + needs: cache_images + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: restore image cache + uses: actions/cache@v4 + with: + path: ~/image-cache + key: base-images-v1 + - name: load cached images + run: docker load -i ~/image-cache/images.tar + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: clippy, rustfmt + - uses: Swatinem/rust-cache@v2 + - name: test database + run: make -C crates/pg test-db + + compile: + name: compile ${{ matrix.service }} + runs-on: ubuntu-latest + strategy: + matrix: + service: + - graphql + - request-create + - request-approve + - rule + - request-by-id + - requests-by-account + - transaction-by-id + - transactions-by-account + - balance-by-account + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + - uses: Swatinem/rust-cache@v2 + with: + shared-key: ${{ matrix.service }} + - name: compile + run: cargo build -p ${{ matrix.service }} + - name: upload binary + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.service }} + path: target/debug/${{ matrix.service }} + retention-days: 1 + + integration_test: + name: integration test in local docker + needs: [cache_images, compile] + runs-on: ubuntu-latest + env: + SERVICES_WORKFLOW: true + steps: + - uses: actions/checkout@v4 + - name: restore image cache + uses: actions/cache@v4 + with: + path: ~/image-cache + key: base-images-v1 + - name: load cached images + run: docker load -i ~/image-cache/images.tar + - name: download all binaries + uses: actions/download-artifact@v4 + with: + path: target/debug/ + merge-multiple: true + - name: set permissions + run: chmod +x target/debug/* + - name: start services + run: make start + - name: test service integration + run: make -C ./tests test-local + - name: clean up + run: make stop + + client_test: + name: client test in local docker + needs: [cache_images, compile] + runs-on: ubuntu-latest + env: + SERVICES_WORKFLOW: true + steps: + - uses: actions/checkout@v4 + - name: restore image cache + uses: actions/cache@v4 + with: + path: ~/image-cache + key: base-images-v1 + - name: load cached images + run: docker load -i ~/image-cache/images.tar + - name: download all binaries + uses: actions/download-artifact@v4 + with: + path: target/debug/ + merge-multiple: true + - name: set permissions + run: chmod +x target/debug/* + - name: start services + run: make start + - name: e2e test client + run: make -C ./client test-ci + - name: clean up + run: make stop + + push_images: + name: push ${{ matrix.service }} image + runs-on: ubuntu-latest + needs: [cache_images, lint_test, unit_test, database_test, integration_test, client_test] + strategy: + matrix: + service: + - graphql + - request-create + - request-approve + - rule + - request-by-id + - requests-by-account + - transaction-by-id + - transactions-by-account + - balance-by-account + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-east-1 + NO_TEST: true + steps: + - uses: actions/checkout@v4 + - name: restore image cache + uses: actions/cache@v4 + with: + path: ~/image-cache + key: base-images-v1 + - name: load cached images + run: docker load -i ~/image-cache/images.tar + - name: mask values + run: echo "::add-mask::${{ secrets.AWS_ACCOUNT_ID }}" + - name: build image + run: make -C services/${{ matrix.service }} build-image + - name: tag image + run: ENV_ID=${{ secrets.DEV_ENV_ID }} make -C services/${{ matrix.service }} tag-dev-image + - name: push image + run: ENV_ID=${{ secrets.DEV_ENV_ID }} make -C services/${{ matrix.service }} push-dev-image diff --git a/.github/workflows/transaction-by-id.yaml b/.github/workflows/transaction-by-id.yaml deleted file mode 100644 index 1a5b85568..000000000 --- a/.github/workflows/transaction-by-id.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: transaction-by-id - -on: - workflow_dispatch: - push: - paths: - - 'services/transaction-by-id/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/transaction-by-id - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/transactions-by-account.yaml b/.github/workflows/transactions-by-account.yaml deleted file mode 100644 index 34ed7eb34..000000000 --- a/.github/workflows/transactions-by-account.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: transactions-by-account - -on: - workflow_dispatch: - push: - paths: - - 'services/transactions-by-account/**' - - 'crates/**' - - 'migrations/schema/*' - branches-ignore: - - 'master' - - 'develop' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - uses: ./.github/workflows/REUSE_service.yaml - with: - app_dir: services/transactions-by-account - secrets: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - DEV_ENV_ID: ${{ secrets.DEV_ENV_ID }} diff --git a/.github/workflows/warm-cache.yaml b/.github/workflows/warm-cache.yaml index 4f010cabb..600f57fc8 100644 --- a/.github/workflows/warm-cache.yaml +++ b/.github/workflows/warm-cache.yaml @@ -47,7 +47,7 @@ jobs: echo "redis key count: $(wc -l < /tmp/redis_keys.txt)" - name: reset rds # reset dev rds to match local postgres seed data - run: ENV_ID=${{ secrets.DEV_ENV_ID }} make -C migrations resetrds + run: ENV_ID=${{ secrets.DEV_ENV_ID }} make -C migrations/go-migrate resetrds - name: warm ddb cache run: | # temporarily add env vars to warm-cache get array so make env fetches them diff --git a/crates/pg/Cargo.toml b/crates/pg/Cargo.toml index be77f3aed..92f207eb6 100644 --- a/crates/pg/Cargo.toml +++ b/crates/pg/Cargo.toml @@ -2,6 +2,7 @@ name = "pg" version = "0.1.0" edition = "2021" +description = "postgresql db access" [dependencies] bb8 = "0.9" diff --git a/crates/pg/makefile b/crates/pg/makefile index 65286c81d..68be1ee75 100644 --- a/crates/pg/makefile +++ b/crates/pg/makefile @@ -1,3 +1,4 @@ +SHELL := /bin/bash RELATIVE_PROJECT_ROOT_PATH=$(shell REL_PATH="."; while [ $$(ls "$$REL_PATH" | grep project.yaml | wc -l | xargs) -eq 0 ]; do REL_PATH="$$REL_PATH./.."; done; printf '%s' "$$REL_PATH") APP_NAME=$(shell basename $(CURDIR)) PROJECT_CONF_FILE_NAME=project.yaml diff --git a/cue/project_conf.cue b/cue/project_conf.cue index 42c3aa84b..021dbc288 100644 --- a/cue/project_conf.cue +++ b/cue/project_conf.cue @@ -86,6 +86,9 @@ infra: { } modules: { env_var!: #EnvVars + codepipeline: { + env_var!: #EnvVars + } environment: { env_var!: #EnvVars } diff --git a/docker/auto-confirm.Dockerfile b/docker/auto-confirm.Dockerfile index 21cd70ff7..b9c082d61 100644 --- a/docker/auto-confirm.Dockerfile +++ b/docker/auto-confirm.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,6 +10,11 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/auto-confirm/Cargo.toml \ --target x86_64-unknown-linux-musl \ diff --git a/docker/balance-by-account.Dockerfile b/docker/balance-by-account.Dockerfile index 814416c20..f0a4b50c4 100644 --- a/docker/balance-by-account.Dockerfile +++ b/docker/balance-by-account.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/balance-by-account/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/balance-by-account /app/balance-by-account diff --git a/docker/bitnami-postgres.Dockerfile b/docker/bitnami-postgres.Dockerfile index 336b39cb1..d383cccc7 100644 --- a/docker/bitnami-postgres.Dockerfile +++ b/docker/bitnami-postgres.Dockerfile @@ -1,4 +1,4 @@ -FROM bitnamilegacy/postgresql:15.3.0 +FROM public.ecr.aws/bitnami/postgresql:15 USER root diff --git a/docker/client-base.Dockerfile b/docker/client-base.Dockerfile deleted file mode 100644 index f38348b79..000000000 --- a/docker/client-base.Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM node:lts-alpine - -WORKDIR /app - -COPY client/package*.json ./ - -RUN npm install \ No newline at end of file diff --git a/docker/client.Dockerfile b/docker/client.Dockerfile index 1bdf36724..2972fa878 100644 --- a/docker/client.Dockerfile +++ b/docker/client.Dockerfile @@ -1,4 +1,4 @@ -FROM mxfactorial/client-base:v1 AS builder1 +FROM public.ecr.aws/docker/library/node:lts-alpine AS builder ARG PUBLIC_POOL_ID ARG PUBLIC_CLIENT_ID @@ -10,19 +10,18 @@ ARG PORT WORKDIR /app -COPY client . +COPY client/package*.json ./ +RUN npm install -# WARNING: docker build was failing to COPY package*.json with unstaged -# changes on macos so npm install may be required before npm run build: -# RUN npm install +COPY client . RUN npm run build -FROM node:lts-alpine +FROM public.ecr.aws/docker/library/node:lts-alpine COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter -COPY --from=builder1 /app/build /app -COPY --from=builder1 /app/package.json /app -COPY --from=builder1 /app/package-lock.json /app +COPY --from=builder /app/build /app +COPY --from=builder /app/package.json /app +COPY --from=builder /app/package-lock.json /app WORKDIR /app -CMD ["node", "index.js"] \ No newline at end of file +CMD ["node", "index.js"] diff --git a/docker/event.Dockerfile b/docker/event.Dockerfile index 0b018ad86..802c50dd6 100644 --- a/docker/event.Dockerfile +++ b/docker/event.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/event/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine:latest +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/event /app/event diff --git a/docker/go-migrate.Dockerfile b/docker/go-migrate.Dockerfile index 313486761..9b7979121 100644 --- a/docker/go-migrate.Dockerfile +++ b/docker/go-migrate.Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:latest AS builder +FROM public.ecr.aws/docker/library/alpine:latest AS builder ARG VERSION=v4.17.0 ARG ARCH=linux-amd64 diff --git a/docker/graphql.Dockerfile b/docker/graphql.Dockerfile index 3fd22d6e6..2a0d28ea6 100644 --- a/docker/graphql.Dockerfile +++ b/docker/graphql.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/graphql/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/graphql /app/graphql diff --git a/docker/measure.Dockerfile b/docker/measure.Dockerfile index a3c57366c..0fa0dd5d8 100644 --- a/docker/measure.Dockerfile +++ b/docker/measure.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/measure/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine:latest +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/measure /app/measure diff --git a/docker/measure.yaml b/docker/measure.yaml new file mode 100644 index 000000000..047ff9d9e --- /dev/null +++ b/docker/measure.yaml @@ -0,0 +1,48 @@ +name: mxf +services: + event: + image: event:latest + build: + context: ../ + dockerfile: ./docker/event.Dockerfile + environment: + PGDATABASE: mxfactorial + PGUSER: test + PGPASSWORD: test + PGHOST: postgres + PGPORT: 5432 + REDIS_DB: 0 + REDIS_HOST: redis + REDIS_PORT: 6379 + REDIS_USERNAME: default + REDIS_PASSWORD: test + depends_on: + redis: + condition: service_healthy + postgres: + condition: service_healthy + measure: + image: measure:latest + build: + context: ../ + dockerfile: ./docker/measure.Dockerfile + ports: + - "10010:10010" + environment: + PGDATABASE: mxfactorial + PGUSER: test + PGPASSWORD: test + PGHOST: postgres + PGPORT: 5432 + REDIS_DB: 0 + REDIS_HOST: redis + REDIS_PORT: 6379 + REDIS_USERNAME: default + REDIS_PASSWORD: test + MEASURE_PORT: 10010 + READINESS_CHECK_PATH: "/healthz" + depends_on: + redis: + condition: service_healthy + postgres: + condition: service_healthy diff --git a/docker/request-approve.Dockerfile b/docker/request-approve.Dockerfile index 1db7c5219..b93b59ebc 100644 --- a/docker/request-approve.Dockerfile +++ b/docker/request-approve.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/request-approve/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/request-approve /app/request-approve diff --git a/docker/request-by-id.Dockerfile b/docker/request-by-id.Dockerfile index f169dff19..09374675c 100644 --- a/docker/request-by-id.Dockerfile +++ b/docker/request-by-id.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/request-by-id/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/request-by-id /app/request-by-id diff --git a/docker/request-create.Dockerfile b/docker/request-create.Dockerfile index bc9d1a1d9..837e9f4ff 100644 --- a/docker/request-create.Dockerfile +++ b/docker/request-create.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/request-create/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/request-create /app/request-create diff --git a/docker/requests-by-account.Dockerfile b/docker/requests-by-account.Dockerfile index 82175bbe2..6fbc153f8 100644 --- a/docker/requests-by-account.Dockerfile +++ b/docker/requests-by-account.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/requests-by-account/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/requests-by-account /app/requests-by-account diff --git a/docker/rule.Dockerfile b/docker/rule.Dockerfile index b549aa43b..d739642ed 100644 --- a/docker/rule.Dockerfile +++ b/docker/rule.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/rule/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/rule /app/rule diff --git a/docker/services.yaml b/docker/services.yaml index 259c530e8..34f420b35 100644 --- a/docker/services.yaml +++ b/docker/services.yaml @@ -19,6 +19,8 @@ services: READINESS_CHECK_PATH: "/healthz" RUST_LOG: info GRAPHQL_PORT: 10000 + GRAPHQL_RESOURCE: query + GRAPHQL_WS_RESOURCE: ws balance-by-account: image: balance-by-account:latest build: @@ -196,53 +198,8 @@ services: TRANSACTIONS_BY_ACCOUNT_PORT: 10008 depends_on: - postgres - event: - image: event:latest - build: - context: ../ - dockerfile: ./docker/event.Dockerfile - environment: - PGDATABASE: mxfactorial - PGUSER: test - PGPASSWORD: test - PGHOST: postgres - PGPORT: 5432 - REDIS_DB: 0 - REDIS_HOST: redis - REDIS_PORT: 6379 - REDIS_USERNAME: default - REDIS_PASSWORD: test - depends_on: - redis: - condition: service_healthy - postgres: - condition: service_healthy - measure: - image: measure:latest - build: - context: ../ - dockerfile: ./docker/measure.Dockerfile - ports: - - "10010:10010" - environment: - PGDATABASE: mxfactorial - PGUSER: test - PGPASSWORD: test - PGHOST: postgres - PGPORT: 5432 - REDIS_DB: 0 - REDIS_HOST: redis - REDIS_PORT: 6379 - REDIS_USERNAME: default - REDIS_PASSWORD: test - MEASURE_PORT: 10010 - READINESS_CHECK_PATH: "/healthz" - depends_on: - redis: - condition: service_healthy - postgres: - condition: service_healthy client: + image: client:latest build: context: ../ dockerfile: ./docker/client.Dockerfile diff --git a/docker/storage.yaml b/docker/storage.yaml index e25bae7cd..c26ed804c 100644 --- a/docker/storage.yaml +++ b/docker/storage.yaml @@ -13,7 +13,7 @@ services: retries: 5 start_period: 10s redis: - image: bitnami/redis:latest + image: public.ecr.aws/bitnami/redis:latest ports: - "6379:6379" healthcheck: diff --git a/docker/transaction-by-id.Dockerfile b/docker/transaction-by-id.Dockerfile index d40ada425..342c90e6f 100644 --- a/docker/transaction-by-id.Dockerfile +++ b/docker/transaction-by-id.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/transaction-by-id/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/transaction-by-id /app/transaction-by-id diff --git a/docker/transactions-by-account.Dockerfile b/docker/transactions-by-account.Dockerfile index ab3f0906b..35239e87b 100644 --- a/docker/transactions-by-account.Dockerfile +++ b/docker/transactions-by-account.Dockerfile @@ -1,4 +1,6 @@ -FROM rust:latest AS builder +FROM public.ecr.aws/docker/library/rust:latest AS builder + +ARG RUN_TESTS=true WORKDIR /app @@ -8,12 +10,17 @@ RUN rustup target add x86_64-unknown-linux-musl RUN apt update && \ apt install -y musl-tools perl make +RUN if [ "$RUN_TESTS" = "true" ]; then rustup component add rustfmt clippy; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo fmt --check; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo clippy -- -D warnings; fi +RUN if [ "$RUN_TESTS" = "true" ]; then cargo test; fi + RUN USER=root cargo build \ --manifest-path=services/transactions-by-account/Cargo.toml \ --target x86_64-unknown-linux-musl \ --release -FROM alpine +FROM public.ecr.aws/docker/library/alpine:latest COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/transactions-by-account /app/transactions-by-account diff --git a/infra/terraform/aws/environments/dev/main.tf b/infra/terraform/aws/environments/dev/main.tf index b4a1249ae..717a1c0c5 100644 --- a/infra/terraform/aws/environments/dev/main.tf +++ b/infra/terraform/aws/environments/dev/main.tf @@ -7,7 +7,7 @@ locals { ARTIFACTS_PREFIX = local.STORAGE_ENV_VAR.ARTIFACTS_BUCKET_PREFIX.default TFSTATE_PREFIX = local.STORAGE_ENV_VAR.TFSTATE_BUCKET_PREFIX.default INFRA_ENV_VAR = local.PROJECT_CONF.infra.terraform.aws.modules.environment.env_var.set - RDS_PREFIX = local.INFRA_ENV_VAR.RDS_PREFIX.default + NAME_PREFIX = local.INFRA_ENV_VAR.NAME_PREFIX.default REGION = local.INFRA_ENV_VAR.REGION.default ENV_ID = module.env_id.ENV_ID ID_ENV = "${local.ENV_ID}-${local.ENV}" @@ -57,7 +57,7 @@ module "dev" { rds_instance_class = "db.t3.micro" rds_parameter_group = "default.postgres14" rds_engine_version = "14.17" - rds_instance_name = "${local.RDS_PREFIX}-${local.ID_ENV}" + rds_instance_name = "${local.NAME_PREFIX}-${local.ID_ENV}" db_snapshot_id = null ############### api gateway ############### diff --git a/infra/terraform/aws/environments/init-dev/main.tf b/infra/terraform/aws/environments/init-dev/main.tf index c1508415e..50a040b9d 100644 --- a/infra/terraform/aws/environments/init-dev/main.tf +++ b/infra/terraform/aws/environments/init-dev/main.tf @@ -28,4 +28,5 @@ module "project_storage_dev" { artifacts_bucket_name_prefix = local.STORAGE_ENV_VAR.ARTIFACTS_BUCKET_PREFIX.default tfstate_bucket_name_prefix = local.STORAGE_ENV_VAR.TFSTATE_BUCKET_PREFIX.default max_image_storage_count = 10 + codebuild_compute_type = "BUILD_GENERAL1_MEDIUM" # SMALL, MEDIUM, LARGE, 2XLARGE } diff --git a/infra/terraform/aws/environments/prod/main.tf b/infra/terraform/aws/environments/prod/main.tf index 393d373a2..b7be562c9 100644 --- a/infra/terraform/aws/environments/prod/main.tf +++ b/infra/terraform/aws/environments/prod/main.tf @@ -15,7 +15,7 @@ locals { ARTIFACTS_PREFIX = local.STORAGE_ENV_VAR.ARTIFACTS_BUCKET_PREFIX.default TFSTATE_PREFIX = local.STORAGE_ENV_VAR.TFSTATE_BUCKET_PREFIX.default INFRA_ENV_VAR = local.PROJECT_CONF.infra.terraform.aws.modules.environment.env_var.set - RDS_PREFIX = local.INFRA_ENV_VAR.RDS_PREFIX.default + NAME_PREFIX = local.INFRA_ENV_VAR.NAME_PREFIX.default REGION = local.INFRA_ENV_VAR.REGION.default ENV_ID = local.PROJECT_CONF.env_var.set.PROD_ENV_ID.default ID_ENV = "${local.ENV_ID}-${local.ENV}" @@ -67,7 +67,7 @@ module "prod" { rds_instance_class = "db.t3.micro" rds_parameter_group = "default.postgres13" rds_engine_version = "13.20" - rds_instance_name = "${local.RDS_PREFIX}-${local.ID_ENV}" + rds_instance_name = "${local.NAME_PREFIX}-${local.ID_ENV}" db_snapshot_id = null ############### api gateway ############### diff --git a/infra/terraform/aws/modules/codebuild/v001/codebuild.tf b/infra/terraform/aws/modules/codebuild/v001/codebuild.tf new file mode 100644 index 000000000..00075e5d3 --- /dev/null +++ b/infra/terraform/aws/modules/codebuild/v001/codebuild.tf @@ -0,0 +1,125 @@ +resource "aws_codebuild_project" "default" { + name = var.project_name + service_role = aws_iam_role.codebuild.arn + + artifacts { + type = "CODEPIPELINE" + } + + environment { + compute_type = var.compute_type + image = "aws/codebuild/standard:7.0" + type = "LINUX_CONTAINER" + privileged_mode = true + + environment_variable { + name = "SERVICE_NAME" + value = var.service_name + } + environment_variable { + name = "ENV_ID" + value = var.env_id + } + environment_variable { + name = "ENV" + value = var.env + } + environment_variable { + name = "AWS_ACCOUNT_ID" + value = var.aws_account_id + } + environment_variable { + name = "REGION" + value = var.aws_region + } + environment_variable { + name = "RUN_TESTS" + value = "true" + } + environment_variable { + name = "PUSH_IMAGE" + value = "true" + } + environment_variable { + name = "DEPLOY" + value = "false" + } + } + + source { + type = "CODEPIPELINE" + buildspec = var.buildspec + } +} + +resource "aws_iam_role" "codebuild" { + name = var.project_name + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "codebuild.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_role_policy" "codebuild" { + name = var.project_name + role = aws_iam_role.codebuild.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + Resource = "*" + }, + { + Effect = "Allow" + Action = [ + "s3:GetObject", + "s3:GetObjectVersion" + ] + Resource = "${var.artifacts_bucket_arn}/*" + }, + { + Effect = "Allow" + Action = [ + "ecr:GetAuthorizationToken" + ] + Resource = "*" + }, + { + Effect = "Allow" + Action = [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:PutImage", + "ecr:InitiateLayerUpload", + "ecr:UploadLayerPart", + "ecr:CompleteLayerUpload" + ] + Resource = var.ecr_repository_arn + }, + { + Effect = "Allow" + Action = [ + "lambda:UpdateFunctionCode" + ] + Resource = var.lambda_function_arn + } + ] + }) +} diff --git a/infra/terraform/aws/modules/codebuild/v001/outputs.tf b/infra/terraform/aws/modules/codebuild/v001/outputs.tf new file mode 100644 index 000000000..3efe80117 --- /dev/null +++ b/infra/terraform/aws/modules/codebuild/v001/outputs.tf @@ -0,0 +1,7 @@ +output "project_name" { + value = aws_codebuild_project.default.name +} + +output "project_arn" { + value = aws_codebuild_project.default.arn +} diff --git a/infra/terraform/aws/modules/codebuild/v001/variables.tf b/infra/terraform/aws/modules/codebuild/v001/variables.tf new file mode 100644 index 000000000..e10579a69 --- /dev/null +++ b/infra/terraform/aws/modules/codebuild/v001/variables.tf @@ -0,0 +1,11 @@ +variable "project_name" {} +variable "service_name" {} +variable "env" {} +variable "env_id" {} +variable "aws_region" {} +variable "aws_account_id" {} +variable "compute_type" {} +variable "buildspec" {} +variable "artifacts_bucket_arn" {} +variable "ecr_repository_arn" {} +variable "lambda_function_arn" {} diff --git a/infra/terraform/aws/modules/codepipeline/v001/codepipeline.tf b/infra/terraform/aws/modules/codepipeline/v001/codepipeline.tf new file mode 100644 index 000000000..e1906e72b --- /dev/null +++ b/infra/terraform/aws/modules/codepipeline/v001/codepipeline.tf @@ -0,0 +1,158 @@ +locals { + ID_ENV = "${var.env_id}-${var.env}" + PROJECT_CONF_FILE_NAME = "project.yaml" + PROJECT_CONF = yamldecode(file("../../../../../${local.PROJECT_CONF_FILE_NAME}")) + CODEPIPELINE_ENV_VAR = local.PROJECT_CONF.infra.terraform.aws.modules.codepipeline.env_var.set + SERVICES_ZIP = local.PROJECT_CONF.scripts.env_var.set.SERVICES_ZIP.default + BUILD_OBJECT_KEY_PATH = local.CODEPIPELINE_ENV_VAR.BUILD_OBJECT_KEY_PATH.default + BUILD_SOURCE_LOCATION = "${local.BUILD_OBJECT_KEY_PATH}/${local.SERVICES_ZIP}" +} + +resource "aws_codepipeline" "build" { + name = "mxfactorial-build-${local.ID_ENV}" + role_arn = aws_iam_role.codepipeline.arn + pipeline_type = "V2" + + artifact_store { + location = var.artifacts_bucket_name + type = "S3" + } + + stage { + name = "Source" + action { + name = "S3Source" + category = "Source" + owner = "AWS" + provider = "S3" + version = "1" + output_artifacts = ["source_output"] + configuration = { + S3Bucket = var.artifacts_bucket_name + S3ObjectKey = local.BUILD_SOURCE_LOCATION + PollForSourceChanges = false + } + } + } + + stage { + name = "Build" + + dynamic "action" { + for_each = var.codebuild_project_names + content { + name = action.key + category = "Build" + owner = "AWS" + provider = "CodeBuild" + input_artifacts = ["source_output"] + version = "1" + run_order = 1 + configuration = { + ProjectName = action.value + } + } + } + } +} + +resource "aws_cloudwatch_event_rule" "s3_trigger" { + name = "mxfactorial-build-trigger-${local.ID_ENV}" + + event_pattern = jsonencode({ + source = ["aws.s3"] + detail-type = ["Object Created"] + detail = { + bucket = { name = [var.artifacts_bucket_name] } + object = { key = [{ prefix = local.BUILD_SOURCE_LOCATION }] } + } + }) +} + +resource "aws_cloudwatch_event_target" "codepipeline" { + rule = aws_cloudwatch_event_rule.s3_trigger.name + arn = aws_codepipeline.build.arn + role_arn = aws_iam_role.eventbridge_pipeline.arn +} + +resource "aws_iam_role" "codepipeline" { + name = "codepipeline-build-${local.ID_ENV}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "codepipeline.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_role_policy" "codepipeline" { + name = "codepipeline-build-${local.ID_ENV}" + role = aws_iam_role.codepipeline.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "s3:GetObject", + "s3:GetObjectVersion", + "s3:GetBucketVersioning", + "s3:PutObject" + ] + Resource = [ + var.artifacts_bucket_arn, + "${var.artifacts_bucket_arn}/*" + ] + }, + { + Effect = "Allow" + Action = [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild" + ] + Resource = "*" + } + ] + }) +} + +resource "aws_iam_role" "eventbridge_pipeline" { + name = "eventbridge-pipeline-${local.ID_ENV}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "events.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_role_policy" "eventbridge_pipeline" { + name = "eventbridge-pipeline-${local.ID_ENV}" + role = aws_iam_role.eventbridge_pipeline.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = "codepipeline:StartPipelineExecution" + Resource = aws_codepipeline.build.arn + } + ] + }) +} diff --git a/infra/terraform/aws/modules/codepipeline/v001/variables.tf b/infra/terraform/aws/modules/codepipeline/v001/variables.tf new file mode 100644 index 000000000..a0831601e --- /dev/null +++ b/infra/terraform/aws/modules/codepipeline/v001/variables.tf @@ -0,0 +1,7 @@ +variable "env" {} +variable "env_id" {} +variable "artifacts_bucket_name" {} +variable "artifacts_bucket_arn" {} +variable "codebuild_project_names" { + type = map(string) +} diff --git a/infra/terraform/aws/modules/ecr/v001/buildspecs/build.yaml b/infra/terraform/aws/modules/ecr/v001/buildspecs/build.yaml new file mode 100644 index 000000000..921613e0b --- /dev/null +++ b/infra/terraform/aws/modules/ecr/v001/buildspecs/build.yaml @@ -0,0 +1,32 @@ +version: 0.2 + +phases: + pre_build: + commands: + - aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com + - export SHORT_SHA=$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION:-$CODEBUILD_BUILD_ID} | sed 's/.*://' | cut -c1-7) + - export ECR_URI=$AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$ENV_ID/$ENV/$SERVICE_NAME + build: + commands: + - echo "building $SERVICE_NAME (RUN_TESTS=$RUN_TESTS, PUSH_IMAGE=$PUSH_IMAGE)..." + - docker build --build-arg RUN_TESTS=$RUN_TESTS -t $SERVICE_NAME:$SHORT_SHA -f docker/$SERVICE_NAME.Dockerfile . + - docker tag $SERVICE_NAME:$SHORT_SHA $ECR_URI:$SHORT_SHA + - docker tag $SERVICE_NAME:$SHORT_SHA $ECR_URI:latest + post_build: + commands: + - | + if [ "$PUSH_IMAGE" = "true" ]; then + echo "pushing $SERVICE_NAME..." + docker push $ECR_URI:$SHORT_SHA + docker push $ECR_URI:latest + else + echo "skipping push (PUSH_IMAGE=$PUSH_IMAGE)" + fi + - | + if [ "$DEPLOY" = "true" ]; then + echo "deploying $SERVICE_NAME to lambda..." + aws lambda update-function-code \ + --function-name $SERVICE_NAME-$ENV_ID-$ENV \ + --image-uri $ECR_URI:latest \ + --region $REGION + fi diff --git a/infra/terraform/aws/modules/ecr/v001/codebuild.tf b/infra/terraform/aws/modules/ecr/v001/codebuild.tf new file mode 100644 index 000000000..7dd30cc70 --- /dev/null +++ b/infra/terraform/aws/modules/ecr/v001/codebuild.tf @@ -0,0 +1,19 @@ +locals { + ID_ENV = "${var.env_id}-${var.env}" +} + +module "codebuild" { + source = "../../codebuild/v001" + + project_name = "mxfactorial-${var.service_name}-${local.ID_ENV}" + service_name = var.service_name + env = var.env + env_id = var.env_id + aws_region = var.aws_region + aws_account_id = var.aws_account_id + compute_type = var.codebuild_compute_type + buildspec = file("${path.module}/buildspecs/build.yaml") + artifacts_bucket_arn = var.artifacts_bucket_arn + ecr_repository_arn = aws_ecr_repository.default.arn + lambda_function_arn = "arn:aws:lambda:${var.aws_region}:${var.aws_account_id}:function:${var.service_name}-${local.ID_ENV}" +} diff --git a/infra/terraform/aws/modules/ecr/v001/outputs.tf b/infra/terraform/aws/modules/ecr/v001/outputs.tf new file mode 100644 index 000000000..ae672401f --- /dev/null +++ b/infra/terraform/aws/modules/ecr/v001/outputs.tf @@ -0,0 +1,11 @@ +output "ecr_repository_url" { + value = aws_ecr_repository.default.repository_url +} + +output "codebuild_project_name" { + value = module.codebuild.project_name +} + +output "codebuild_project_arn" { + value = module.codebuild.project_arn +} diff --git a/infra/terraform/aws/modules/ecr/v001/variables.tf b/infra/terraform/aws/modules/ecr/v001/variables.tf index b841b14be..210fd1e81 100644 --- a/infra/terraform/aws/modules/ecr/v001/variables.tf +++ b/infra/terraform/aws/modules/ecr/v001/variables.tf @@ -1,8 +1,12 @@ variable "env" {} variable "env_id" {} variable "force_delete" { - type = bool + type = bool default = false } variable "service_name" {} -variable "max_image_storage_count" {} \ No newline at end of file +variable "max_image_storage_count" {} +variable "artifacts_bucket_arn" {} +variable "aws_region" {} +variable "aws_account_id" {} +variable "codebuild_compute_type" {} \ No newline at end of file diff --git a/infra/terraform/aws/modules/project-storage/v001/README.md b/infra/terraform/aws/modules/project-storage/v001/README.md new file mode 100644 index 000000000..3b58b67b2 --- /dev/null +++ b/infra/terraform/aws/modules/project-storage/v001/README.md @@ -0,0 +1,131 @@ +
+
+