diff --git a/.cz.yaml b/.cz.yaml index fafd24e..08836a2 100644 --- a/.cz.yaml +++ b/.cz.yaml @@ -1,8 +1,7 @@ --- commitizen: + changelog_incremental: true name: cz_conventional_commits - tag_format: aws_fargate_service-${version} update_changelog_on_bump: true version: 0.1.0 - changelog_file: aws/fargate_service/CHANGELOG.md - changelog_incremental: true + version_scheme: semver2 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0f17867 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.github/workflows/branch.yaml b/.github/workflows/branch.yaml new file mode 100644 index 0000000..d893dd8 --- /dev/null +++ b/.github/workflows/branch.yaml @@ -0,0 +1,46 @@ +name: Branch Checks + +on: + push: + branches-ignore: + - main + +jobs: + lint: + name: Lint updated files + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - uses: actions/cache@v4 + name: Cache plugin directory + with: + path: ~/.tflint.d/plugins + key: tflint-${{ hashFiles('.tflint.hcl') }} + - uses: terraform-linters/setup-tflint@v4 + name: Setup TFLint + - name: Show version + run: tflint --version + - name: Init TFLint + run: tflint --init + - name: Run TFLint + run: tflint --format compact --recursive + + trivy: + name: Run security scan + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - name: Run Trivy vulnarability scanner + uses: aquasecurity/trivy-action@master + with: + scan-type: config + format: sarif + output: "trivy-results.sarif" + - name: Parse SARIF file + # Always run this step, even if a previous step failed. + if: always() + uses: Ayrx/sarif_to_github_annotations@v0.2.2 + with: + sarif_file: "trivy-results.sarif" diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml new file mode 100644 index 0000000..04ac6d2 --- /dev/null +++ b/.github/workflows/codeql-analysis.yaml @@ -0,0 +1,47 @@ +name: CodeQL + +on: + push: + branches: + - main + pull_request: + branches: + - main + schedule: + - cron: '45 13 * * *' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + # Using "javascript" to scan JSON and YAML files. + language: [ 'javascript' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + queries: security-extended,security-and-quality + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..78b68cd --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,46 @@ +name: Main Checks + +on: + push: + branches: + - main + +jobs: + lint: + name: Lint updated modules + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - uses: actions/cache@v4 + name: Cache plugin directory + with: + path: ~/.tflint.d/plugins + key: tflint-${{ hashFiles('.tflint.hcl') }} + - uses: terraform-linters/setup-tflint@v4 + name: Setup TFLint + - name: Show version + run: tflint --version + - name: Init TFLint + run: tflint --init + - name: Run TFLint + run: tflint --format compact --recursive + + trivy: + name: Run security scan + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - name: Run Trivy vulnarability scanner + uses: aquasecurity/trivy-action@master + with: + scan-type: config + format: sarif + output: "trivy-results.sarif" + - name: Upload SARIF result + # Always run this step, even if a previous step failed. + if: always() + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: "trivy-results.sarif" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..5dd5f63 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,98 @@ +name: Release New Version + +on: + push: + branches: + - main + +jobs: + # Builds a new release for the module by bumping the version number and + # generating a changelog entry. Commit the changes and open a pull request. + build-release: + name: Build new release + runs-on: ubuntu-latest + if: ${{ !startsWith(github.event.head_commit.message, 'bump:') }} + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - name: Bump version and create changelog + id: bump + uses: commitizen-tools/commitizen-action@master + with: + push: false + github_token: ${{ secrets.GITHUB_TOKEN }} + git_redirect_stderr: true + - name: Get the commit message + id: message + run: | + MESSAGE=$(git log --format=%B -n 1) + echo "message=${MESSAGE}" >> $GITHUB_OUTPUT + - name: Open a pull request for the release + uses: peter-evans/create-pull-request@v7 + with: + branch: release-${{ steps.bump.outputs.version }} + title: ${{ steps.message.outputs.message }} + + # Creates a new tag and GitHub release for the module. + release: + name: Release module + runs-on: ubuntu-latest + if: startsWith(github.event.head_commit.message, 'bump:') + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - name: Get the module name + id: module_name + run: | + REPO_NAME="${{ github.event.repository.name }}" + REPO_NAME="${REPO_NAME/tofu-modules-/}" + MODULE_NAME="${REPO_NAME//-/_}" + echo "name=${MODULE_NAME}" >> $GITHUB_OUTPUT + - name: Get the version from the commit message + id: version + uses: actions/github-script@v7 + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + with: + result-encoding: string + # Look for the last version number, expecting it to be in the format: + # `#.#.#-.#` where the suffix is optional. + script: | + const message = process.env.COMMIT_MESSAGE; + const regex = /^bump:.+(?\d+\.\d+\.\d+[\da-z.-]*) \(#\d+\)$/m; + const version = message.match(regex).groups.version; + console.log(version); + return version; + - name: Bundle the module + # We create an empty file first, so that tar doesn't complain about the + # contents changing while it's running. + run: | + touch '${{ steps.module_name.outputs.name }}-${{ steps.version.outputs.result }}.tar.gz' + tar \ + --exclude='.git' \ + --exclude='.gitignore' \ + --exclude='.github' \ + --exclude='.cz.yaml' \ + --exclude='*.tar.gz' \ + --exclude='*.tfvars' \ + --exclude='release.md' \ + --exclude='CODEOWNERS' \ + --exclude='trivy.yaml' \ + --exclude='*.env' \ + -czf '${{ steps.module_name.outputs.name }}-${{ steps.version.outputs.result }}.tar.gz' \ + . + - name: Get changelog entry + id: changelog + uses: artlaman/conventional-changelog-reader-action@v1.1.0 + with: + version: ${{ steps.version.outputs.result }} + - name: Create release + uses: softprops/action-gh-release@v2 + with: + body: | + ## ${{ steps.changelog.outputs.version }} (${{ steps.changelog.outputs.date }}) + + ${{ steps.changelog.outputs.changes }} + tag_name: ${{ steps.version.outputs.result }} + files: | + ${{ steps.module_name.outputs.name }}-${{ steps.version.outputs.result }}.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c5482d1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json +.env + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Ignore the plan output of command: terraform plan -out=tfplan +*tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# Ignore release artifacts +release.md +/*.tar.gz diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..93cd166 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @codeforamerica/devops diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..347cab4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# Contributing + +## Commit message format + +All commit messages should follow the [Conventional Commits][commits] format. +This format allows us to automatically generate changelogs and version numbers +based on the commit messages. + +Common commit types include: + +* `fix`: A bug fix +* `feat`: A new feature +* `ci`: Changes to CI/CD +* `docs`: Changes to documentation + +adding `!` after the type indicates a breaking change. For example, `feat!` +would indicate a new feature that breaks existing functionality, and would +therefore require a major version bump. + +`bump` is a special type used to indicate a version bump. This is used by the +automated release process, and should be avoided in normal commits. + +## Coding standards + +Code should follow the [OpenTofu style conventions][style]. This ensures that +all code is consistent and easy to read and maintain. + +To make resources easier to find, you may group them together in a single file +within your module. For example, while `main.tf` handles the main configuration, +you may create a `dns.tf` file to handle all DNS-related resources. + +Additionally, the following should be grouped together within their own files: + +* `data.tf` for data sources +* `local.tf` for local values +* `output.tf` for outputs + +## Code reviews + +All code should be contributing in the form of a pull request. Pull requests +should have an approval from _at least_ one required reviewer as defined in the +`CODEOWNERS` file. Additional reviews are welcome, and may be requested by +either the submitter or the required reviewer. + +[commits]: https://www.conventionalcommits.org/en/v1.0.0/ +[style]: https://opentofu.org/docs/language/syntax/style/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e44ffed --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Code for America + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index bb1b6d5..6d3981f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # AWS Fargate Service Module +[![Main Checks][badge-checks]][code-checks] [![GitHub Release][badge-release]][latest-release] + This module launches a service on AWS Fargate. It creates a cluster, task definition, service, and container repository. In addition, it creates the load balancer, ACM certificate, Route53 records, and security groups needed to expose @@ -12,7 +14,7 @@ to match your desired configuration. For example: ```hcl module "fargate_service" { - source = "github.com/codeforamerica/tofu-modules/aws/fargate_service" + source = "github.com/codeforamerica/tofu-modules-aws-fargate_service?ref=1.0.0" project = "my-project" project_short = "my-proj" @@ -143,9 +145,14 @@ secrets_manager_secrets = { | repository_arn | ARN of the ECR repository, if created. | `string` | | repository_url | URL for the container image. | `string` | +[badge-checks]: https://github.com/codeforamerica/tofu-modules-aws-fargate-service/actions/workflows/main.yaml/badge.svg +[badge-release]: https://img.shields.io/github/v/release/codeforamerica/tofu-modules-aws-fargate-service?logo=github&label=Latest%20Release +[code-checks]: https://github.com/codeforamerica/tofu-modules-aws-fargate-service/actions/workflows/main.yaml [container_command]: #container_command [ecs-exec]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html [environment_secrets]: #environment_secrets +[latest-release]: https://github.com/codeforamerica/tofu-modules-aws-fargate-service/releases/latest [secrets]: https://github.com/codeforamerica/tofu-modules-aws-secrets [secrets-manager]: https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html [secrets_manager_secrets]: #secrets_manager_secrets +[tofu-modules]: https://github.com/codeforamerica/tofu-modules diff --git a/trivy.yaml b/trivy.yaml new file mode 100644 index 0000000..16c3805 --- /dev/null +++ b/trivy.yaml @@ -0,0 +1,14 @@ +exit-code: 1 +misconfiguration: + ignore-unfixed: true + terraform: + exclude-downloaded-modules: true +scan: + scanners: + - misconfig + skip-dirs: + - "**/*/.terraform" +exclude: + # If we want to use the common "latest" tag in ECR, we have to allow mutable + # tags. + - aws-ecr-enforce-immutable-repository