Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions modules/gh-repo-secrets-section/.terraform-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
formatter: "markdown"

version: ""

header-from: docs/header.md
footer-from: docs/footer.md

recursive:
enabled: false
path: modules
include-main: true

sections:
hide: []
show: []

content: ""

output:
file: "README.md"
mode: inject
template: |-
<!-- BEGIN_TF_DOCS -->
{{ .Content }}
<!-- END_TF_DOCS -->
output-values:
enabled: false
from: ""

sort:
enabled: true
by: name

settings:
anchor: true
color: true
default: true
description: false
escape: true
hide-empty: false
html: true
indent: 2
lockfile: true
read-comments: true
required: true
sensitive: true
type: true
117 changes: 117 additions & 0 deletions modules/gh-repo-secrets-section/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<!-- BEGIN_TF_DOCS -->
# **GitHub Repository Secrets Terraform Module**

## Overview

This module manages GitHub repository secrets for **Actions**, **Codespaces**, and **Dependabot** using a single strongly-typed `config` object.

**Important**:
The `encryptedValue` values passed in the `config` **must already be encrypted** using **libsodium** against the target repository’s public key (GitHub’s recommended method).
**Terraform does not perform any encryption**. It simply forwards the pre-encrypted value to the GitHub API.

This approach is the most secure for automated pipelines (Prefapp IDP, GitHub Actions, etc.).

## Key Features

- **Single complex object**: All secrets are defined in one `config` variable.
- **Pre-encrypted values**: `encryptedValue` must be provided already encrypted with libsodium.
- **Three secret types**: Actions, Codespaces, and Dependabot supported in the same module.
- **Lifecycle protection**: `ignore_changes` on `encrypted_value` to prevent unnecessary drift.
- **Full validation**: Enforces required fields and non-empty values.
- **JSON-native**: Works seamlessly with `terraform.tfvars.json` generated by external programs.

## Basic Usage

### Using `terraform.tfvars.json` (recommended)

```hcl
module "repo_secrets" {
source = "git::https://github.com/prefapp/tfm.git//modules/github-repository-secrets"

config = var.config # Terraform automatically loads terraform.tfvars.json
}

### Inline example

Manages GitHub secrets for **one repository only**.

```hcl
module "secrets" {
source = "github.com/prefapp/tfm//modules/gh-repo-secrets-section"

config = {
repository = "prefapp/tfm"

actions = {
"MY\_API\_KEY" = "r+RFBGIn8U7z2Opm5RN7PXKdgFzefXiV91IpG3O2DrClZl9dkTJBfhRZbi2uV2nu..."
}
codespaces = {}
dependabot = {}
}
}
```
```

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.0 |
| <a name="requirement_github"></a> [github](#requirement\_github) | ~> 6.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_github"></a> [github](#provider\_github) | ~> 6.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [github_actions_secret.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret) | resource |
| [github_codespaces_secret.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/codespaces_secret) | resource |
| [github_dependabot_secret.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/dependabot_secret) | resource |
| [github_repository.this](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/repository) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_config"></a> [config](#input\_config) | Complete configuration object for this module (single repository only).<br/><br/>• repository = GitHub repo in 'owner/repo' format (required)<br/>• actions / codespaces / dependabot = map of secret\_name => encrypted\_value<br/>• encrypted\_value must be pre-encrypted with libsodium using the repo's public key. | <pre>object({<br/> repository = string<br/><br/> actions = optional(map(string), {})<br/> codespaces = optional(map(string), {})<br/> dependabot = optional(map(string), {})<br/> })</pre> | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_actions_secret_names"></a> [actions\_secret\_names](#output\_actions\_secret\_names) | List of created Actions secret names |
| <a name="output_all_secret_names"></a> [all\_secret\_names](#output\_all\_secret\_names) | Combined list of all secret names |
| <a name="output_codespaces_secret_names"></a> [codespaces\_secret\_names](#output\_codespaces\_secret\_names) | List of created Codespaces secret names |
| <a name="output_dependabot_secret_names"></a> [dependabot\_secret\_names](#output\_dependabot\_secret\_names) | List of created Dependabot secret names |
| <a name="output_repository"></a> [repository](#output\_repository) | The repository these secrets belong to |

### 3. `docs/footer.md`
```markdown
## Examples

For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/github-repository-secrets/_examples):

- [basic](https://github.com/prefapp/tfm/tree/main/modules/github-repository-secrets/_examples/basic) - Full example with Actions, Codespaces, and Dependabot secrets

## Resources

- **github_actions_secret**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret)
- **github_codespaces_secret**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/codespaces_secret)
- **github_dependabot_secret**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/dependabot_secret)
- **GitHub Terraform Provider**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs)

## Support

For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).

```
<!-- END_TF_DOCS -->
5 changes: 5 additions & 0 deletions modules/gh-repo-secrets-section/_examples/basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module "repo_secrets" {
source = "git::https://github.com/prefapp/tfm.git//modules/gh-repo-secrets-section"

config = var.config # Terraform automatically loads terraform.tfvars.json
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"config": {
"actions": {
"SECRET_A": "ENCRYPTED_SECRET_A_PLACEHOLDER",

"SECRET_B": "ENCRYPTED_SECRET_B_PLACEHOLDER"
},
"codespaces": {
"SECRET_C": "ENCRYPTED_SECRET_C_PLACEHOLDER"
},
"dependabot": {}
}
}
16 changes: 16 additions & 0 deletions modules/gh-repo-secrets-section/docs/footer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Examples

For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/gh-repo-secrets-section/_examples):

- [basic](https://github.com/prefapp/tfm/tree/main/modules/gh-repo-secrets-section/_examples/basic) - Full example with Actions, Codespaces, and Dependabot secrets

## Resources

- **github_actions_secret**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret)
- **github_codespaces_secret**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/codespaces_secret)
- **github_dependabot_secret**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/dependabot_secret)
- **GitHub Terraform Provider**: [Official Documentation](https://registry.terraform.io/providers/integrations/github/latest/docs)

## Support

For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
53 changes: 53 additions & 0 deletions modules/gh-repo-secrets-section/docs/header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# **GitHub Repository Secrets Terraform Module**

## Overview

This module manages GitHub repository secrets for **Actions**, **Codespaces**, and **Dependabot** using a single strongly-typed `config` object.

**Important**:
The `encryptedValue` values passed in the `config` **must already be encrypted** using **libsodium** against the target repository’s public key (GitHub’s recommended method).
**Terraform does not perform any encryption**. It simply forwards the pre-encrypted value to the GitHub API.

This approach is the most secure for automated pipelines (Prefapp IDP, GitHub Actions, etc.).

## Key Features

- **Single complex object**: All secrets are defined in one `config` variable.
- **Pre-encrypted values**: `encryptedValue` must be provided already encrypted with libsodium.
- **Three secret types**: Actions, Codespaces, and Dependabot supported in the same module.
- **Lifecycle protection**: `ignore_changes` on `encrypted_value` to prevent unnecessary drift.
- **Full validation**: Enforces required fields and non-empty values.
- **JSON-native**: Works seamlessly with `terraform.tfvars.json` generated by external programs.

## Basic Usage

### Using `terraform.tfvars.json` (recommended)

```hcl
module "repo_secrets" {
source = "git::https://github.com/prefapp/tfm.git//modules/gh-repo-secrets-section"

config = var.config # Terraform automatically loads terraform.tfvars.json
}
```

### Inline example

Manages GitHub secrets for **one repository only**.

```hcl
<<<<<<< HEAD
module "repo_secrets" {
source = "git::https://github.com/prefapp/tfm.git//modules/gh-repo-secrets-section"

config = {
repository = "prefapp/tfm"

actions = {
"MY_API_KEY" = "r+RFBGIn8U7z2Opm5RN7PXKdgFzefXiV91IpG3O2DrClZl9dkTJBfhRZbi2uV2nu..."
}
codespaces = {}
dependabot = {}
}
}
```
51 changes: 51 additions & 0 deletions modules/gh-repo-secrets-section/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# ─────────────────────────────────────────────────────────────
# Fetch repository info (validates existence + gives canonical name)
# ─────────────────────────────────────────────────────────────
data "github_repository" "this" {
full_name = var.config.repository
}

# ─────────────────────────────────────────────────────────────
# GitHub Actions Secrets
# ─────────────────────────────────────────────────────────────
resource "github_actions_secret" "this" {
for_each = var.config.actions

repository = data.github_repository.this.name
secret_name = each.key
encrypted_value = each.value

lifecycle {
ignore_changes = [encrypted_value]
}
}

# ─────────────────────────────────────────────────────────────
# GitHub Codespaces Secrets
# ─────────────────────────────────────────────────────────────
resource "github_codespaces_secret" "this" {
for_each = var.config.codespaces

repository = data.github_repository.this.name
secret_name = each.key
encrypted_value = each.value

lifecycle {
ignore_changes = [encrypted_value]
}
}

# ─────────────────────────────────────────────────────────────
# GitHub Dependabot Secrets
# ─────────────────────────────────────────────────────────────
resource "github_dependabot_secret" "this" {
for_each = var.config.dependabot

repository = data.github_repository.this.name
secret_name = each.key
encrypted_value = each.value

lifecycle {
ignore_changes = [encrypted_value]
}
}
28 changes: 28 additions & 0 deletions modules/gh-repo-secrets-section/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
output "repository" {
description = "The repository these secrets belong to"
value = var.config.repository
}

output "actions_secret_names" {
description = "List of created Actions secret names"
value = keys(var.config.actions)
}

output "codespaces_secret_names" {
description = "List of created Codespaces secret names"
value = keys(var.config.codespaces)
}

output "dependabot_secret_names" {
description = "List of created Dependabot secret names"
value = keys(var.config.dependabot)
}

output "all_secret_names" {
description = "Combined list of all secret names"
value = concat(
keys(var.config.actions),
keys(var.config.codespaces),
keys(var.config.dependabot)
)
}
24 changes: 24 additions & 0 deletions modules/gh-repo-secrets-section/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
variable "config" {
description = <<-EOT
Complete configuration object for this module (single repository only).

• repository = GitHub repo in 'owner/repo' format (required)
• actions / codespaces / dependabot = map of secret_name => encrypted_value
• encrypted_value must be pre-encrypted with libsodium using the repo's public key.
EOT

type = object({
repository = string

actions = optional(map(string), {})
codespaces = optional(map(string), {})
dependabot = optional(map(string), {})
})

validation {
condition = can(regex("^[a-zA-Z0-9_-]+/[a-zA-Z0-9_.-]+$", var.config.repository))
error_message = "config.repository must be in 'owner/repo' format."
}

nullable = false
}
10 changes: 10 additions & 0 deletions modules/gh-repo-secrets-section/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.5.0"

required_providers {
github = {
source = "integrations/github"
version = "~> 6.0"
}
}
}
3 changes: 3 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@
"modules/aws-secretsmanager-replication": {
"package-name": "aws-secretsmanager-replication"
},
"modules/gh-repo-secrets-section": {
"package-name": "gh-repo-secrets-section"
},
"modules/azure-vnet-gateway": {
"package-name": "azure-vnet-gateway"
},
Expand Down