GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com β€” GitHub - microsoftexpert/terraform-github-codespaces: Terraform module: terraform-github-codespaces

BranchesTags
Open more actions menu

Latest commit

 

History

1 Commit
1 Commit

Folders and files

NameName
Last commit message
Last commit date
.gitignore
.gitignore
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
SCOPE.md
SCOPE.md
 
 
main.tf
main.tf
 
 
outputs.tf
outputs.tf
 
 
providers.tf
providers.tf
 
 
variables.tf
variables.tf
 
 

Repository files navigation

πŸ™ GitHub Codespaces Secrets Terraform Module

One secure-by-default boundary for every GitHub Codespaces secret β€” repository, organization, and user scope β€” plus the selected-repository allow-list that pairs with selected-visibility org secrets. Private-by-default org visibility, encrypted_value preferred over plaintext, sensitive inputs, and zero secret values in outputs. Built for integrations/github v6.x.

Terraform GitHub provider module type resources


🧩 Overview

This is an aggregation module β€” a Codespaces secrets bundle. It has no single primary resource; instead it groups four independent, role-named for_each collections behind one boundary, each defaulting to {} so you enable only the scopes you use:

  • πŸ”‘ Repository secrets (repository_secrets) β€” Codespaces secrets scoped to a single repository.
  • 🏒 Organization secrets (organization_secrets) β€” org-wide Codespaces secrets with all / private / selected visibility (default private).
  • 🎯 Selected-repository allow-lists (secret_repository_access) β€” the repository allow-list that a selected-visibility org secret reads from, managed as its own resource.
  • πŸ‘€ User secrets (user_secrets) β€” Codespaces secrets scoped to the authenticated user, optionally granted to specific repositories.

πŸ’‘ Why it matters: Codespaces secrets feed live developer environments with credentials. This module makes that surface declarative, least-privilege, and auditable β€” secrets are sensitive inputs, org secrets default to private, and only names and resource ids are ever emitted. It is the direct mirror of terraform-github-dependabot, one scope up to include the user-level secret, so secrets-by-feature stay consistent across Dependabot / Actions / Codespaces.


❀️ Support this project

If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:

  • ⭐ Star this repository to help others discover this Terraform module.
  • 🀝 Connect with me on LinkedIn: linkedin.com/in/microsoftexpert
  • β˜• Buy me a coffee: buymeacoffee.com/microsoftexpert

Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!


πŸ—ΊοΈ Where this fits in the family

The keystone terraform-github-repository emits the repository name (id) and numeric id (repo_id) that this module consumes; the other secret-family siblings consume the same keystone. This module emits only names and ids β€” to audit/reporting tooling, never to another module's secret input.

flowchart LR
 repo["πŸ—οΈ terraform-github-repository<br/>keystone"]
 cs["πŸ™ terraform-github-codespaces<br/>(this module)"]
 dep["terraform-github-dependabot"]
 act["terraform-github-actions-repository"]
 audit["πŸ“Š Audit / Reporting"]

 repo -->|"id = repo name"| cs
 repo -->|"repo_id (numeric)"| cs
 repo -.-> dep
 repo -.-> act
 cs -->|"*_secret_names / *_secret_ids"| audit

 style cs fill:#8957E5,color:#fff
 style repo fill:#24292F,color:#fff
Loading

πŸ”Œ Consumes: repository name (repo secrets) and numeric repo_id (org selected allow-lists + user-secret access) from terraform-github-repository. Emits: per-scope secret-name sets and id maps for audit/reporting. See the Cross-Module Contract.


🧬 What this module builds

There is no this resource. The diagram shows the four independent role-named collections; the only internal relationship is that a selected-visibility org secret pairs with the allow-list resource (own that allow-list in exactly one place).

flowchart TD
 rs["var.repository_secrets<br/>map(object) β€” sensitive"] --> repo["github_codespaces_secret.repo<br/>for_each"]
 os["var.organization_secrets<br/>map(object) β€” sensitive"] --> org["github_codespaces_organization_secret.org<br/>for_each"]
 sra["var.secret_repository_access<br/>map(object)"] --> allow["github_codespaces_organization_secret_repositories.allow<br/>for_each"]
 us["var.user_secrets<br/>map(object) β€” sensitive"] --> user["github_codespaces_user_secret.user<br/>for_each"]
 org -.->|"visibility = selected<br/>allow-list owned in one place"| allow

 style repo fill:#8957E5,color:#fff
 style org fill:#8957E5,color:#fff
 style allow fill:#8957E5,color:#fff
 style user fill:#8957E5,color:#fff
Loading

Resource inventory

  • github_codespaces_secret.repo β€” repository-scoped Codespaces secrets, one per repository_secrets entry.
  • github_codespaces_organization_secret.org β€” organization-scoped Codespaces secrets with visibility, one per organization_secrets entry.
  • github_codespaces_organization_secret_repositories.allow β€” the selected-repository allow-list for a selected-visibility org secret, one per secret_repository_access entry.
  • github_codespaces_user_secret.user β€” user-scoped Codespaces secrets, one per user_secrets entry.

βœ… Provider / Versions

  • Terraform >= 1.12.0
  • integrations/github ~> 6.0 β€” validated against 6.12.1
  • Never hashicorp/github (deprecated). Migrate old state with terraform state replace-provider registry.terraform.io/hashicorp/github registry.terraform.io/integrations/github.

ℹ️ 6.x schema notes surfaced during authoring:

  • No key_id argument. All Codespaces secret resources accept encrypted_value (Base64) and plaintext_value only β€” there is no key_id field. The provider resolves the appropriate Codespaces public key internally. Pre-encrypt against the right public key data source and pass just the encrypted_value.
  • No visibility on user secrets. github_codespaces_user_secret has no visibility; it takes an optional selected_repository_ids that grants repositories access to the secret inside the user's Codespaces.
  • Only created_at / updated_at are computed. These resources expose no node_id, slug, repo_id, or html_url β€” the cross-module reference is the resource id.

πŸ“ Module Structure

terraform-github-codespaces/
β”œβ”€β”€ providers.tf # github provider requirement (~> 6.0); NO provider {} block
β”œβ”€β”€ variables.tf # four role-named map(object) collections; secret-bearing ones sensitive
β”œβ”€β”€ main.tf # repo / org / allow / user collections (no 'this'); nonsensitive(keys) pattern
β”œβ”€β”€ outputs.tf # per-scope name sets + id maps; NEVER a secret value
β”œβ”€β”€ README.md # this file
└── SCOPE.md # token scopes, prerequisites, consumes/emits contract, gotchas

βš™οΈ Quick Start

The smallest useful call defines a single repository Codespaces secret. Every collection defaults to {}, so you supply only the scopes you need.

module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  repository_secrets = {
    npm_token = {
      repository      = "loan-origination-svc"
      secret_name     = "NPM_TOKEN"
      encrypted_value = var.npm_token_encrypted # Base64, pre-encrypted with the repo Codespaces public key
    }
  }
}

ℹ️ The organization and authentication are the provider's owner / GITHUB_OWNER and token/App β€” never module variables. Point the provider at the target org before applying.


πŸ”Œ Cross-Module Contract

Sourced directly from SCOPE.md.

Consumes

Input Type Source
repository_secrets[].repository string (repo name) terraform-github-repository β†’ id
organization_secrets[].selected_repository_ids list(number) terraform-github-repository β†’ repo_id
secret_repository_access[].selected_repository_ids list(number) terraform-github-repository β†’ repo_id
user_secrets[].selected_repository_ids list(number) terraform-github-repository β†’ repo_id

Emits

Output Description Consumed by
repository_secret_names Set of managed repo Codespaces secret names (values never emitted) Audit / drift detection
repository_secret_ids Map: handle β†’ github_codespaces_secret resource id Reporting
organization_secret_names Set of managed org Codespaces secret names Audit
organization_secret_ids Map: handle β†’ github_codespaces_organization_secret resource id Reporting
user_secret_names Set of managed user Codespaces secret names Audit
user_secret_ids Map: handle β†’ github_codespaces_user_secret resource id Reporting
secret_repository_access_ids Map: handle β†’ github_codespaces_organization_secret_repositories resource id Reporting

πŸ”’ No secret value is ever output. Only names and resource ids are emitted.


πŸ“š Example Library

Every collection is keyed by a stable caller handle (the map key) β€” never a list index. Examples use the new GitHub-org source and sibling terraform-github-* references.

1 Β· Minimal β€” one repository secret
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  repository_secrets = {
    npm_token = {
      repository      = "loan-origination-svc"
      secret_name     = "NPM_TOKEN"
      plaintext_value = var.npm_token # provider encrypts on write
    }
  }
}

πŸ’‘ Supply exactly one of plaintext_value or encrypted_value per secret.

2 Β· Organization secret β€” visibility = all
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  organization_secrets = {
    shared_registry = {
      secret_name     = "SHARED_REGISTRY_TOKEN"
      visibility      = "all" # every repo in the org, including public
      plaintext_value = var.shared_registry_token
    }
  }
}

⚠️ all exposes the secret to every repository, including public ones. Prefer private or selected at a regulated institution.

3 Β· Organization secret β€” visibility = private (secure default)
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  organization_secrets = {
    artifactory = {
      secret_name = "ARTIFACTORY_TOKEN"
      # visibility omitted β†’ defaults to "private" (all private/internal repos)
      encrypted_value = var.artifactory_token_encrypted
    }
  }
}
4 Β· Organization secret β€” visibility = selected, allow-list managed separately
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  organization_secrets = {
    payments_key = {
      secret_name     = "PAYMENTS_API_KEY"
      visibility      = "selected"
      encrypted_value = var.payments_key_encrypted
      # NOTE: do NOT set selected_repository_ids inline β€” owned by the allow-list below.
    }
  }

  secret_repository_access = {
    payments_key = {
      secret_name             = "PAYMENTS_API_KEY"
      selected_repository_ids = [12345678, 23456789] # numeric repo ids
    }
  }
}

πŸ”’ Own each selected secret's allow-list in exactly one place β€” here, or inline via selected_repository_ids on the secret (example 5), never both.

5 Β· Organization secret β€” visibility = selected, allow-list inline
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  organization_secrets = {
    payments_key = {
      secret_name             = "PAYMENTS_API_KEY"
      visibility              = "selected"
      encrypted_value         = var.payments_key_encrypted
      selected_repository_ids = [12345678, 23456789] # inline allow-list
    }
  }
  # Do not also add a secret_repository_access entry for PAYMENTS_API_KEY.
}
6 Β· User secret
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  user_secrets = {
    gh_pat = {
      secret_name     = "PERSONAL_GH_PAT"
      plaintext_value = var.personal_gh_pat
    }
  }
}

ℹ️ User secrets attach to the authenticated user (the provider identity), not the org. They need the codespace:secrets classic scope.

7 Β· User secret granted to specific repositories
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  user_secrets = {
    gh_pat = {
      secret_name             = "PERSONAL_GH_PAT"
      encrypted_value         = var.personal_gh_pat_encrypted
      selected_repository_ids = [12345678] # repos that may read the secret in the user's Codespaces
    }
  }
}
8 Β· encrypted_value everywhere (preferred over plaintext)
# Encrypt against the matching Codespaces public key BEFORE Terraform runs.
data "github_codespaces_public_key" "repo" {
  repository = "loan-origination-svc"
}

module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  repository_secrets = {
    db_password = {
      repository      = "loan-origination-svc"
      secret_name     = "DB_PASSWORD"
      encrypted_value = var.db_password_encrypted # Base64, encrypted with the repo public key
    }
  }
}

πŸ”’ Prefer encrypted_value: the plaintext never enters your HCL. (Note: there is no key_id argument β€” the provider resolves the public key internally; you supply only the Base64 ciphertext.) State always holds the value regardless β€” keep your backend encrypted.

9 Β· for_each at scale β€” many repo secrets from one map(object)
variable "repo_codespaces_secrets" {
  type = map(object({
    repository      = string
    secret_name     = string
    encrypted_value = string
  }))
  default   = {}
  sensitive = true
}

module "codespaces" {
  source             = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"
  repository_secrets = var.repo_codespaces_secrets
}

⚠️ Each secret is one API write plus a public-key fetch. Large maps can trip secondary rate limits β€” split very large applies.

10 Β· Mixed scopes in a single call
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  repository_secrets = {
    npm = { repository = "web-portal", secret_name = "NPM_TOKEN", encrypted_value = var.npm_enc }
  }

  organization_secrets = {
    artifactory = { secret_name = "ARTIFACTORY_TOKEN", visibility = "private", encrypted_value = var.arti_enc }
  }

  user_secrets = {
    gh_pat = { secret_name = "PERSONAL_GH_PAT", encrypted_value = var.pat_enc }
  }
}
11 Β· Repository secrets wired from terraform-github-repository (cross-module)
module "repository" {
  source     = "git::https://github.com/microsoftexpert/terraform-github-repository?ref=v1.0.0"
  name       = "loan-origination-svc"
  visibility = "private"
}

module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  repository_secrets = {
    npm_token = {
      repository      = module.repository.id # repo NAME from the keystone
      secret_name     = "NPM_TOKEN"
      encrypted_value = var.npm_token_encrypted
    }
  }
}
12 Β· Selected org secret wired by numeric repo_id (cross-module)
module "repository" {
  source     = "git::https://github.com/microsoftexpert/terraform-github-repository?ref=v1.0.0"
  name       = "payments-svc"
  visibility = "private"
}

module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  organization_secrets = {
    payments_key = {
      secret_name     = "PAYMENTS_API_KEY"
      visibility      = "selected"
      encrypted_value = var.payments_key_encrypted
    }
  }

  secret_repository_access = {
    payments_key = {
      secret_name             = "PAYMENTS_API_KEY"
      selected_repository_ids = [module.repository.repo_id] # NUMERIC id from the keystone
    }
  }
}
13 Β· πŸ”’ Secure / hardened variant β€” encrypted everywhere, selected, least repos
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  # Repo secrets: encrypted_value only, never plaintext in code.
  repository_secrets = {
    db = {
      repository      = module.repository.id
      secret_name     = "DB_PASSWORD"
      encrypted_value = var.db_password_encrypted
    }
  }

  # Org secrets: selected visibility, the narrowest possible allow-list.
  organization_secrets = {
    payments_key = {
      secret_name     = "PAYMENTS_API_KEY"
      visibility      = "selected"
      encrypted_value = var.payments_key_encrypted
    }
  }
  secret_repository_access = {
    payments_key = {
      secret_name             = "PAYMENTS_API_KEY"
      selected_repository_ids = [module.repository.repo_id] # exactly the repos that need it
    }
  }
}

πŸ”’ Hardened posture: encrypted_value everywhere, org secrets selected (never all), allow-lists scoped to the minimum repositories, secrets are sensitive inputs, no values in outputs.

14 Β· Consuming the outputs for audit / reporting
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"
  #... collections...
}

output "managed_codespaces_secret_names" {
  value = {
    repository   = module.codespaces.repository_secret_names
    organization = module.codespaces.organization_secret_names
    user         = module.codespaces.user_secret_names
  }
}

# Assert the org never holds an unexpected Codespaces secret (drift detection).
check "no_unexpected_org_secret" {
  assert {
    condition     = !contains(module.codespaces.organization_secret_names, "LEGACY_TOKEN")
    error_message = "A retired Codespaces org secret (LEGACY_TOKEN) is still managed."
  }
}

ℹ️ Outputs are names and ids only β€” never values. Each map/set is empty ({} / []) when its scope is unused, never null.

15 Β· πŸ—οΈ End-to-end composition (mandatory finale) β€” repository β†’ codespaces, outputs β†’ inputs
# 1) Keystone repository.
module "repository" {
  source               = "git::https://github.com/microsoftexpert/terraform-github-repository?ref=v1.0.0"
  name                 = "loan-origination-svc"
  visibility           = "private"
  vulnerability_alerts = true
}

# 2) Codespaces secrets wired entirely from the keystone's outputs.
module "codespaces" {
  source = "git::https://github.com/microsoftexpert/terraform-github-codespaces?ref=v1.0.0"

  # repo name β†’ repository_secrets[].repository
  repository_secrets = {
    npm_token = {
      repository      = module.repository.id
      secret_name     = "NPM_TOKEN"
      encrypted_value = var.npm_token_encrypted
    }
  }

  # org secret, selected visibility
  organization_secrets = {
    payments_key = {
      secret_name     = "PAYMENTS_API_KEY"
      visibility      = "selected"
      encrypted_value = var.payments_key_encrypted
    }
  }

  # numeric repo_id β†’ allow-list
  secret_repository_access = {
    payments_key = {
      secret_name             = "PAYMENTS_API_KEY"
      selected_repository_ids = [module.repository.repo_id]
    }
  }
}

output "codespaces_repo_secret_ids" {
  value = module.codespaces.repository_secret_ids
}

πŸ’‘ The keystone emits id (the repo name) and repo_id (the numeric id). The name flows into repo-secret entries; the numeric id flows into selected allow-lists. Apply the repository before the secrets.


πŸ“₯ Inputs

All four inputs are map(object(...)) keyed by a stable caller handle, each defaulting to {} (independently optional). The three secret-bearing collections are sensitive = true.

  • repository_secrets (sensitive) β€” repo-scoped secrets. Required per entry: repository, secret_name. Optional: plaintext_value, encrypted_value (supply one; prefer encrypted).
  • organization_secrets (sensitive) β€” org-scoped secrets. Required: secret_name. Optional: visibility (default private; validated all/private/selected), plaintext_value, encrypted_value, selected_repository_ids (inline allow-list, default []).
  • secret_repository_access (not sensitive) β€” allow-lists for selected org secrets. Required: secret_name, selected_repository_ids.
  • user_secrets (sensitive) β€” user-scoped secrets. Required: secret_name. Optional: plaintext_value, encrypted_value, selected_repository_ids (repos granted access, default []).
Full object schemas
variable "repository_secrets" {
  type = map(object({
    repository      = string
    secret_name     = string
    plaintext_value = optional(string)
    encrypted_value = optional(string)
  }))
  default   = {}
  sensitive = true
}

variable "organization_secrets" {
  type = map(object({
    secret_name             = string
    visibility              = optional(string, "private") # all | private | selected
    plaintext_value         = optional(string)
    encrypted_value         = optional(string)
    selected_repository_ids = optional(list(number), [])
  }))
  default   = {}
  sensitive = true
  # validation: visibility ∈ {all, private, selected}
}

variable "secret_repository_access" {
  type = map(object({
    secret_name             = string
    selected_repository_ids = list(number)
  }))
  default = {}
}

variable "user_secrets" {
  type = map(object({
    secret_name             = string
    plaintext_value         = optional(string)
    encrypted_value         = optional(string)
    selected_repository_ids = optional(list(number), [])
  }))
  default   = {}
  sensitive = true
}

🧾 Outputs

Output Description
repository_secret_ids Map: handle β†’ github_codespaces_secret resource id. Empty {} when unused.
repository_secret_names Set of managed repository Codespaces secret names.
organization_secret_ids Map: handle β†’ github_codespaces_organization_secret resource id.
organization_secret_names Set of managed organization Codespaces secret names.
secret_repository_access_ids Map: handle β†’ github_codespaces_organization_secret_repositories resource id.
user_secret_ids Map: handle β†’ github_codespaces_user_secret resource id.
user_secret_names Set of managed user Codespaces secret names.

πŸ”’ No output is sensitive β€” and none is a secret value. Only names and resource ids are emitted; structural fields are revealed with nonsensitive. Every map/set is empty (not null) when its scope is unused.


🧠 Architecture Notes

  • Aggregation shape β€” no this. There is no single dominant resource; each scope is a peer for_each collection named by role (repo, org, allow, user). This mirrors terraform-github-dependabot (repo + org + allow) one scope up, adding github_codespaces_user_secret.
  • sensitive inputs + nonsensitive(keys). repository_secrets, organization_secrets, and user_secrets are sensitive = true because they carry secret values. Terraform forbids for_each over a sensitive value, so main.tf iterates nonsensitive(toset(keys(...))) and indexes the map inside each resource. Non-secret structural fields (repository, secret_name, visibility) are revealed with nonsensitive so plan output and outputs stay useful; the secret value flows straight through to the schema-sensitive plaintext_value / encrypted_value arguments.
  • encrypted_value preferred β€” and there is no key_id. Prefer encrypted_value (pre-encrypted, Base64) over plaintext_value so plaintext never enters HCL. These resources expose no key_id argument β€” the provider resolves the Codespaces public key internally. ⚠️ Either way the value lives in state β€” keep the backend encrypted.
  • Org visibility & the one-place allow-list rule. organization_secrets[].visibility is all / private / selected (default private, validated). For selected, own the allow-list in exactly one place: inline selected_repository_ids on the secret or a secret_repository_access entry β€” never both for the same secret, or they fight over the same allow-list.
  • Values are write-only; names/ids are the only outputs. The provider cannot read a secret's value back, so it cannot detect remote-value drift β€” changing a value in code re-writes it; a value changed only in the GitHub UI is invisible to Terraform. Secret names are tracked. On import, the provider does not fetch the value (terraform import github_codespaces_secret.repo[\"handle\"] repo/SECRET_NAME; org/user import by secret name) β€” you may need ignore_changes on the value as a workaround.
  • No tags, no timeouts. GitHub has no resource tagging concept and these resources expose no timeouts block β€” there is no tags/timeouts tail (the key difference from the azurerm/aws libraries).

🧱 Design Principles

  • πŸ”’ Private by default β€” org-secret visibility defaults to private, never all/public. Wider exposure is an explicit, reviewed opt-in.
  • πŸ—οΈ Encrypt over plaintext β€” encrypted_value is the documented preference so secrets never sit in HCL; plaintext_value is the fallback.
  • πŸ™ˆ Secrets are sensitive β€” every secret-bearing input map is sensitive = true; no secret value is ever emitted as an output.
  • 🎯 Least privilege β€” selected org secrets scope to the minimum repositories; allow-lists are owned in one place to avoid accidental over-grant.
  • 🧩 Composable, auth-free β€” no provider {} block, no owner/token/app_auth variables; the caller configures auth and the target org. integrations/github only β€” never hashicorp/github.
  • 🧾 Auditable β€” emits exactly the names and ids audit/reporting tooling needs, and nothing more.

πŸš€ Runbook

terraform init -backend=false
terraform validate
terraform fmt -check
terraform plan
terraform apply
terraform output

⚠️ Always pin the module to a tag β€” ?ref=v1.0.0 β€” never a branch. Codespaces secrets feed live developer environments at a regulated institution; a moving ref is unacceptable.


πŸ§ͺ Testing

Offline proof gate (no live org required):

terraform fmt -check # zero formatting differences
terraform validate # configuration is valid
tflint # core rules (no dedicated GitHub ruleset exists)

βœ… This module passes terraform init -backend=false, terraform validate ("Success! The configuration is valid."), and terraform fmt -check (zero diffs) against integrations/github 6.12.1.


πŸ’¬ Example Output

repository_secret_ids = {
 "npm_token" = "loan-origination-svc:NPM_TOKEN"
}
repository_secret_names = toset([
 "NPM_TOKEN",
])
organization_secret_ids = {
 "payments_key" = "PAYMENTS_API_KEY"
}
organization_secret_names = toset([
 "PAYMENTS_API_KEY",
])
secret_repository_access_ids = {
 "payments_key" = "PAYMENTS_API_KEY"
}
user_secret_ids = {}
user_secret_names = toset([])

πŸ” Troubleshooting

Symptom Cause Resolution
Invalid for_each argument / "sensitive value" on plan A secret-bearing map was iterated directly The module already uses for_each = nonsensitive(toset(keys(...))); if you adapt it, never for_each a sensitive value directly.
403 / Resource not accessible on org secrets Provider identity lacks org rights Token/App needs admin:org (classic) or Organization β†’ Codespaces secrets: read/write (fine-grained). See SCOPE.md.
403 on user secrets Missing user scope Classic PAT needs codespace:secrets; fine-grained needs Codespaces user secrets: read/write on the user.
Apply fails creating any Codespaces secret Codespaces not enabled for the org / not billed Enable Codespaces and configure billing first. Many regulated orgs disable Codespaces β€” confirm it is part of the footprint.
Org secret apply fails on a Free org Org Codespaces secrets need Team / Enterprise Cloud Upgrade the plan or scope secrets to repo/user level.
selected_repository_ids rejected / no effect Wrong id type, or set on a non-selected secret Use numeric repo_id (wire module.repository.repo_id), and only with visibility = "selected".
Allow-list keeps reverting Allow-list owned in two places Set selected_repository_ids inline or via secret_repository_access for a given secret β€” never both.
Value changed in the GitHub UI not detected Values are write-only The provider can't read values back; re-apply from code (the source of truth), or use ignore_changes for externally-rotated secrets.
Secondary rate limit on a big apply Many secrets = many writes + key fetches Split large for_each maps across applies.

πŸ”— Related Docs

  • integrations/github provider β€” Codespaces Secret, Codespaces Organization Secret, Codespaces Organization Secret Repositories, and Codespaces User Secret resource references
  • integrations/github provider β€” Codespaces public-key data sources (repo / organization / user) for encrypted_value
  • module β€” terraform-github-repository (keystone; emits id and repo_id)
  • module β€” terraform-github-dependabot (the direct mirror β€” repo + org + allow-list)
  • module β€” terraform-github-actions-repository / terraform-github-repository-environment (sibling secrets surfaces)
  • GitHub Docs β€” Managing encrypted secrets for your Codespaces, and the Codespaces organization/billing policy matrix

About

Terraform module: terraform-github-codespaces

Topics

cloud-infrastructuredeveloper-platformdevopsencryption-at-restgithubiacinfrastructure-as-codeterraformterraform-module

Resources

Readme
MIT license
Activity

Stars

0 stars

Watchers

0 watching

Forks

0 forks
Report repository

Releases

Packages

Contributors

Languages

You are visitor 01402503 β€” GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800Γ—600. No cookies required.