diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 168011c..eb1d555 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -1,52 +1,29 @@ -name: 'Validate PR title' +name: Validate PR title on: pull_request_target: - types: - - opened - - edited - - synchronize + types: [opened, edited, synchronize] + +permissions: + pull-requests: read jobs: - main: - name: Validate PR title + validate: runs-on: ubuntu-latest steps: - # Please look up the latest version from - # https://github.com/amannn/action-semantic-pull-request/releases - - uses: amannn/action-semantic-pull-request@v3.4.6 + - uses: amannn/action-semantic-pull-request@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - # Configure which types are allowed. - # Default: https://github.com/commitizen/conventional-commit-types types: | fix feat docs ci chore - # Configure that a scope must always be provided. + style + revert requireScope: false - # Configure additional validation for the subject based on a regex. - # This example ensures the subject starts with an uppercase character. - subjectPattern: ^[A-Z].+$ - # If `subjectPattern` is configured, you can use this property to override - # the default error message that is shown when the pattern doesn't match. - # The variables `subject` and `title` can be used within the message. - subjectPatternError: | - The subject "{subject}" found in the pull request title "{title}" - didn't match the configured pattern. Please ensure that the subject - starts with an uppercase character. - # For work-in-progress PRs you can typically use draft pull requests - # from Github. However, private repositories on the free plan don't have - # this option and therefore this action allows you to opt-in to using the - # special "[WIP]" prefix to indicate this state. This will avoid the - # validation of the PR title and the pull request checks remain pending. - # Note that a second check will be reported if this is enabled. - wip: true - # When using "Squash and merge" on a PR with only one commit, GitHub - # will suggest using that commit message instead of the PR title for the - # merge commit, and it's easy to commit this by mistake. Enable this option - # to also validate the commit message for one commit PRs. + subjectPattern: ^[a-z].+$ + subjectPatternError: "The subject must start with a lowercase character." validateSingleCommit: false diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml deleted file mode 100644 index 956986a..0000000 --- a/.github/workflows/pre-commit.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Pre-Commit - -on: - pull_request: - branches: - - main - - master - -env: - TERRAFORM_DOCS_VERSION: v0.16.0 - -jobs: - collectInputs: - name: Collect workflow inputs - runs-on: ubuntu-latest - outputs: - directories: ${{ steps.dirs.outputs.directories }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Get root directories - id: dirs - uses: clowdhaus/terraform-composite-actions/directories@v1.3.0 - - preCommitMinVersions: - name: Min TF pre-commit - needs: collectInputs - runs-on: ubuntu-latest - strategy: - matrix: - directory: ${{ fromJson(needs.collectInputs.outputs.directories) }} - steps: - - run: git config --global url."https://".insteadOf git:// - - name: Checkout - uses: actions/checkout@v3 - - - name: Terraform min/max versions - id: minMax - uses: clowdhaus/terraform-min-max@v1.0.3 - with: - directory: ${{ matrix.directory }} - - - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} - # Run only validate pre-commit check on min version supported - if: ${{ matrix.directory != '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.3.0 - with: - terraform-version: ${{ steps.minMax.outputs.minVersion }} - args: 'terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*' - - - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} - # Run only validate pre-commit check on min version supported - if: ${{ matrix.directory == '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.3.0 - with: - terraform-version: ${{ steps.minMax.outputs.minVersion }} - args: 'terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)' - - #preCommitMaxVersion: - # name: Max TF pre-commit - # runs-on: ubuntu-latest - # needs: collectInputs - # steps: - # - run: git config --global url."https://".insteadOf git:// - # - name: Checkout - # uses: actions/checkout@v3 - # with: - # ref: ${{ github.event.pull_request.head.ref }} - # repository: ${{github.event.pull_request.head.repo.full_name}} -# - # - name: Terraform min/max versions - # id: minMax - # uses: clowdhaus/terraform-min-max@v1.0.3 -# - # - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} - # uses: clowdhaus/terraform-composite-actions/pre-commit@v1.3.0 - # with: - # terraform-version: ${{ steps.minMax.outputs.maxVersion }} - # terraform-docs-version: ${{ env.TERRAFORM_DOCS_VERSION }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 045f4e8..b6c2306 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,35 +1,33 @@ name: Release on: - workflow_dispatch: push: - branches: - - main - - master + branches: [master] paths: - - '**/*.tpl' - - '**/*.py' - - '**/*.tf' - - '.github/workflows/release.yml' + - "**/*.tf" + - ".releaserc.json" + - ".github/workflows/release.yml" + +permissions: + contents: write + issues: write + pull-requests: write jobs: release: - name: Release runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: - persist-credentials: false fetch-depth: 0 + persist-credentials: false - - name: Release - uses: cycjimmy/semantic-release-action@v2 + - uses: cycjimmy/semantic-release-action@v5.0.2 with: - semantic_version: 18.0.0 + semantic_version: 25.0.8 extra_plugins: | - @semantic-release/changelog@6.0.0 - @semantic-release/git@10.0.0 - conventional-changelog-conventionalcommits@4.6.3 + @semantic-release/changelog@6.0.3 + @semantic-release/git@10.0.1 + conventional-changelog-conventionalcommits@8.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..5396875 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,38 @@ +name: Validate Terraform module + +on: + pull_request: + push: + branches: [master] + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: hashicorp/setup-terraform@v3 + with: + terraform_version: "0.13.1" + terraform_wrapper: false + + - uses: terraform-linters/setup-tflint@v6 + with: + tflint_version: v0.58.0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install pre-commit + run: pipx install pre-commit + + - name: Validate root module + run: | + terraform fmt -check -recursive + terraform init -backend=false + terraform validate + pre-commit run --all-files diff --git a/.gitignore b/.gitignore index 397af32..2bf9373 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ crash.log # control as they are data points which are potentially sensitive and subject # to change depending on the environment. *.tfvars +*.tfvars.json # Ignore override files as they are usually used to override resources locally and so # are not checked in diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 10db981..95acafc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,37 +1,36 @@ repos: -- repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.68.1 - hooks: - - id: terraform_fmt - - id: terraform_validate - - id: terraform_tflint - args: - - '--args=--only=terraform_deprecated_interpolation' - - '--args=--only=terraform_deprecated_index' - - '--args=--only=terraform_unused_declarations' - - '--args=--only=terraform_comment_syntax' - - '--args=--only=terraform_documented_outputs' - - '--args=--only=terraform_documented_variables' - - '--args=--only=terraform_typed_variables' - - '--args=--only=terraform_module_pinned_source' - - '--args=--only=terraform_naming_convention' - - '--args=--only=terraform_required_version' - - '--args=--only=terraform_required_providers' - - '--args=--only=terraform_standard_module_structure' - - '--args=--only=terraform_workspace_remote' -- repo: local - hooks: - - id: terraform-docs - name: terraform-docs - language: docker_image - entry: quay.io/terraform-docs/terraform-docs:latest - args: ["markdown", "--output-file", "README.md", "--output-mode", "replace", "./"] - pass_filenames: false -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + - repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.108.0 hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - exclude: README.md - - id: check-added-large-files - - id: detect-aws-credentials + - id: terraform_fmt + - id: terraform_validate + files: ^(main|variables|outputs|versions)\.tf$ + - id: terraform_tflint + files: ^(main|variables|outputs|versions)\.tf$ + args: + - --args=--only=terraform_deprecated_interpolation + - --args=--only=terraform_deprecated_index + - --args=--only=terraform_unused_declarations + - --args=--only=terraform_documented_outputs + - --args=--only=terraform_documented_variables + - --args=--only=terraform_typed_variables + - --args=--only=terraform_required_version + - --args=--only=terraform_required_providers + - --args=--only=terraform_standard_module_structure + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + exclude: README.md + - id: check-added-large-files + - id: detect-aws-credentials + args: [--allow-missing-credentials] + - repo: local + hooks: + - id: terraform-docs + name: Terraform docs + language: docker_image + entry: quay.io/terraform-docs/terraform-docs:0.20.0 + args: ["markdown", "table", "--output-file", "README.md", "--output-mode", "inject", "."] + pass_filenames: false diff --git a/.releaserc.json b/.releaserc.json index 66b3eef..dad592f 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -1,45 +1,21 @@ { - "branches": [ - "main", - "master" - ], + "branches": ["master"], "ci": false, "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits" - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits" - } - ], - [ - "@semantic-release/github", - { - "successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:", - "labels": false, - "releasedLabels": false - } - ], - [ - "@semantic-release/changelog", - { - "changelogFile": "CHANGELOG.md", - "changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file." - } - ], - [ - "@semantic-release/git", - { - "assets": [ - "CHANGELOG.md" - ], - "message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" - } - ] + ["@semantic-release/commit-analyzer", { "preset": "conventionalcommits" }], + ["@semantic-release/release-notes-generator", { "preset": "conventionalcommits" }], + ["@semantic-release/changelog", { + "changelogFile": "CHANGELOG.md", + "changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file." + }], + ["@semantic-release/github", { + "successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:", + "labels": false, + "releasedLabels": false + }], + ["@semantic-release/git", { + "assets": ["CHANGELOG.md"], + "message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + }] ] } diff --git a/.terraform-version b/.terraform-version new file mode 100644 index 0000000..c317a91 --- /dev/null +++ b/.terraform-version @@ -0,0 +1 @@ +0.13.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..2255844 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Contributing + +Contributions that improve this Terraform module are welcome. Please keep each +change focused, documented, and validated before opening a pull request. + +## Prerequisites + +- The Terraform version declared in `.terraform-version`. +- Docker, used by the `terraform-docs` pre-commit hook. +- Python with `pre-commit` installed. For example: `pipx install pre-commit`. + +## Local validation + +Before opening a pull request, run: + +```shell +tfswitch +pre-commit run --all-files +``` + +The command formats Terraform, validates the root module, runs TFLint, checks +for credentials, and refreshes generated Terraform documentation in +`README.md`. Do not manually edit content between Terraform Docs markers. + +## Pull requests + +- Create a branch from the repository default branch and keep the pull request + focused on one change. +- Describe the behavior being changed and include an example when the module + interface changes. +- Ensure the GitHub Actions validation workflow passes before requesting review. +- Use a Conventional Commit-compatible pull request title. Allowed types are + `feat`, `fix`, `docs`, `ci`, `chore`, `style`, and `revert`. The + subject must start with a lowercase character. + +## Releases + +Releases are automated by Semantic Release after changes are merged into the +repository default branch. It determines the next semantic version from +Conventional Commits, creates the Git tag and GitHub Release, and updates +`CHANGELOG.md`. + +- `fix:` produces a patch release. +- `feat:` produces a minor release. +- A commit with `!` in its type or scope, or a `BREAKING CHANGE:` footer, + produces a major release. + +The Terraform Registry is connected to this repository once by the module +owner. After initial registration, Registry versions are indexed from Semantic +Release Git tags. diff --git a/README.md b/README.md index bf7ac65..34c1ac7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +## Compatibility + +This module requires Terraform 0.13.1 or later. Older Terraform versions are not supported. + ## Requirements @@ -10,7 +14,7 @@ | Name | Version | |------|---------| -| [aws](#provider\_aws) | 4.12.1 | +| [aws](#provider\_aws) | >= 3.63 | ## Modules @@ -21,6 +25,7 @@ No modules. | Name | Type | |------|------| | [aws_codebuild_project.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_project) | resource | +| [aws_codestarnotifications_notification_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codestarnotifications_notification_rule) | resource | | [aws_iam_policy.additional](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.service_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.codebuild_role_extra_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | @@ -64,7 +69,7 @@ No modules. | [codebuild\_secondary\_source\_location](#input\_codebuild\_secondary\_source\_location) | The location of the source code from git or s3. | `string` | `null` | no | | [codebuild\_secondary\_source\_report\_build\_status](#input\_codebuild\_secondary\_source\_report\_build\_status) | Set to true to report the status of a build's start and finish to your source provider. This option is only valid when the type is `BITBUCKET` or `GITHUB`. | `bool` | `false` | no | | [codebuild\_secondary\_source\_type](#input\_codebuild\_secondary\_source\_type) | The type of repository that contains the secondary source code to be built. Valid values for this parameter are: `CODECOMMIT`, `CODEPIPELINE`, `GITHUB`, `GITHUB_ENTERPRISE`, `BITBUCKET`, `S3` or `NO_SOURCE`. | `string` | `"CODEPIPELINE"` | no | -| [codebuild\_secondary\_sources](#input\_codebuild\_secondary\_sources) | Information about the project's secondary sources code. See the related codebuild source objects for descriptions of each parameter.
The parameter `source_identifier` is the name of the directory to clone the secondary source into as a sibling to the primary source code directory.
If this variable is omitted, no secondary sources are created.
eg:
codebuild_secondary_sources = [
{
type = "GITHUB"
location = "https://github.com/myprofile/myproject-1.git"
source_identifier = "my_awesome_project1"
},
{
type = "GITHUB"
location = "https://github.com/myprofile/myproject-2.git"
git_clone_depth = 1
source_identifier = "my_awesome_project2"
report_build_status = true
insecure_ssl = true
}
]
| `any` | `[]` | no | +| [codebuild\_secondary\_sources](#input\_codebuild\_secondary\_sources) | Information about the project's secondary sources code. See the related codebuild source objects for descriptions of each parameter.
The parameter `source_identifier` is the name of the directory to clone the secondary source into as a sibling to the primary source code directory.
If this variable is omitted, no secondary sources are created.
eg:
codebuild_secondary_sources = [
{
type = "GITHUB"
location = "https://github.com/myprofile/myproject-1.git"
source_identifier = "my_awesome_project1"
},
{
type = "GITHUB"
location = "https://github.com/myprofile/myproject-2.git"
git_clone_depth = 1
source_identifier = "my_awesome_project2"
report_build_status = true
insecure_ssl = true
}
]
| `any` | `[]` | no | | [codebuild\_source](#input\_codebuild\_source) | Information about the project's input source code. | `any` | `{}` | no | | [codebuild\_source\_auth](#input\_codebuild\_source\_auth) | Information about the authorization settings for AWS CodeBuild to access the source code to be built. | `map(any)` | `{}` | no | | [codebuild\_source\_buildspec](#input\_codebuild\_source\_buildspec) | The build spec declaration to use for this build project's related builds. This must be set when type is iNO\_SOURCE | `string` | `null` | no | @@ -78,6 +83,7 @@ No modules. | [codebuild\_source\_version](#input\_codebuild\_source\_version) | A version of the build input to be built for this project. If not specified, the latest version is used. | `string` | `null` | no | | [concurrent\_build\_limit](#input\_concurrent\_build\_limit) | Specify a maximum number of concurrent builds for the project. | `number` | `1` | no | | [create\_default\_service\_role](#input\_create\_default\_service\_role) | Should the default service role be created? | `bool` | `true` | no | +| [create\_notification\_rule](#input\_create\_notification\_rule) | (Required) Create notification rule. | `bool` | `false` | no | | [description](#input\_description) | A short description of the project. | `string` | `null` | no | | [encryption\_key](#input\_encryption\_key) | The AWS Key Management Service (AWS KMS) customer master key (CMK) to be used for encrypting the build project's build output artifacts. | `string` | `null` | no | | [environment](#input\_environment) | Information about the project's build environment. | `any` | `{}` | no | @@ -90,6 +96,8 @@ No modules. | [environment\_type](#input\_environment\_type) | The type of build environment to use for related builds. Available values are: `LINUX_CONTAINER`, `LINUX_GPU_CONTAINER`, `WINDOWS_CONTAINER` or `ARM_CONTAINER`. | `string` | `"LINUX_CONTAINER"` | no | | [environment\_variables](#input\_environment\_variables) | A list of sets of environment variables to make available to builds for this build project. | `list(any)` | `[]` | no | | [name](#input\_name) | The projects name. | `string` | n/a | yes | +| [notification\_rule\_event\_type\_ids](#input\_notification\_rule\_event\_type\_ids) | (Required) A list of event types associated with this notification rule. | `list(any)` |
[
"codebuild-project-build-state-failed",
"codebuild-project-build-state-succeeded",
"codebuild-project-build-state-in-progress",
"codebuild-project-build-state-stopped",
"codebuild-project-build-phase-failure",
"codebuild-project-build-phase-success"
]
| no | +| [notification\_rule\_target](#input\_notification\_rule\_target) | (Optional) Configuration blocks containing notification target information. Can be specified multiple times. At least one target must be specified on creation. | `list(any)` | `[]` | no | | [queued\_timeout](#input\_queued\_timeout) | How long in minutes, from 5 to 480 (8 hours), a build is allowed to be queued before it times out.The default is 8 hours. | `number` | `480` | no | | [s3\_logs](#input\_s3\_logs) | Configuration for the builds to store log data to S3. | `any` | `{}` | no | | [s3\_logs\_encryption\_disabled](#input\_s3\_logs\_encryption\_disabled) | Set to true if you do not want S3 logs encrypted. | `string` | `true` | no | @@ -112,4 +120,4 @@ No modules. | [service\_role\_arn](#output\_service\_role\_arn) | Amazon Resource Name (ARN) of the Service Role for CodeBuild. | | [service\_role\_id](#output\_service\_role\_id) | ID of the Service Role created for CodeBuild. | | [service\_role\_name](#output\_service\_role\_name) | Name of the Service Role created for CodeBuild. | - \ No newline at end of file + diff --git a/iam.tf b/iam.tf index 6ba2c4e..0b8a0c3 100644 --- a/iam.tf +++ b/iam.tf @@ -2,14 +2,14 @@ resource "aws_iam_role" "service_role" { count = var.create_default_service_role ? 1 : 0 name = "${var.name}-service-role" - assume_role_policy = element(data.aws_iam_policy_document.codebuild_assume_role_policy.*.json, 0) + assume_role_policy = data.aws_iam_policy_document.codebuild_assume_role_policy[0].json } # Add extra polcies resource "aws_iam_role_policy" "codebuild_role_extra_policies" { count = var.create_default_service_role ? 1 : 0 - role = element(aws_iam_role.service_role.*.name, 0) - policy = element(data.aws_iam_policy_document.codebuild_role_extra_policies.*.json, 0) + role = aws_iam_role.service_role[0].name + policy = data.aws_iam_policy_document.codebuild_role_extra_policies[0].json } # Assume Role diff --git a/locals.tf b/locals.tf index 496f88c..c35a066 100644 --- a/locals.tf +++ b/locals.tf @@ -104,5 +104,5 @@ locals { security_group_ids = lookup(var.vpc_config, "security_group_ids", null) == null ? var.vpc_config_security_group_ids : lookup(var.vpc_config, "security_group_ids") } - service_role_arn = var.create_default_service_role ? element(aws_iam_role.service_role.*.arn, 0) : var.service_role_arn + service_role_arn = var.create_default_service_role ? aws_iam_role.service_role[0].arn : var.service_role_arn } diff --git a/outputs.tf b/outputs.tf index ede26c6..07741b3 100644 --- a/outputs.tf +++ b/outputs.tf @@ -15,15 +15,15 @@ output "name" { output "service_role_name" { description = "Name of the Service Role created for CodeBuild." - value = var.create_default_service_role ? element(aws_iam_role.service_role.*.name, 0) : null + value = var.create_default_service_role ? aws_iam_role.service_role[0].name : null } output "service_role_arn" { description = "Amazon Resource Name (ARN) of the Service Role for CodeBuild." - value = var.create_default_service_role ? element(aws_iam_role.service_role.*.arn, 0) : null + value = var.create_default_service_role ? aws_iam_role.service_role[0].arn : null } output "service_role_id" { description = "ID of the Service Role created for CodeBuild." - value = var.create_default_service_role ? element(aws_iam_role.service_role.*.id, 0) : null + value = var.create_default_service_role ? aws_iam_role.service_role[0].id : null }