diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..522506c
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,34 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
+{
+ "name": "Ubuntu",
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+ "image": "mcr.microsoft.com/devcontainers/base:jammy",
+ "features": {
+ "ghcr.io/devcontainers/features/terraform:1": {},
+ "ghcr.io/devcontainers-contrib/features/terraform-docs:1": {},
+ "ghcr.io/devcontainers/features/azure-cli:1": {},
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {},
+ "ghcr.io/devcontainers-contrib/features/kind:1": {},
+ "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {},
+ "ghcr.io/dhoeric/features/stern:1": {}
+ },
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "github.vscode-github-actions",
+ "redhat.vscode-yaml"
+ ]
+ }
+ }
+ // Features to add to the dev container. More info: https://containers.dev/features.
+ // "features": {},
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ // "forwardPorts": [],
+ // Use 'postCreateCommand' to run commands after the container is created.
+ // "postCreateCommand": "uname -a",
+ // Configure tool-specific properties.
+ // "customizations": {},
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+ // "remoteUser": "root"
+}
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..3c92f18
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,28 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ # Check for updates to GitHub Actions every week
+ interval: "weekly"
+ reviewers:
+ - infinite-automations/admins
+ - package-ecosystem: "terraform"
+ directory: "/"
+ schedule:
+ # Check for updates to terraform every week
+ interval: "weekly"
+ reviewers:
+ - infinite-automations/admins
+ - package-ecosystem: "terraform"
+ directory: "examples/full"
+ schedule:
+ # Check for updates to terraform every week
+ interval: "weekly"
+ reviewers:
+ - infinite-automations/admins
diff --git a/.github/workflows/test-and-release.yml b/.github/workflows/test-and-release.yml
new file mode 100644
index 0000000..1214cd4
--- /dev/null
+++ b/.github/workflows/test-and-release.yml
@@ -0,0 +1,158 @@
+name: Test & Release
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+permissions:
+ actions: read
+ contents: write
+ statuses: read
+
+env:
+ TF_VAR_github_app_id: ${{ secrets.GH_APP_ID }}
+ TF_VAR_github_app_install_id: ${{ secrets.GH_APP_INSTALL_ID }}
+ TF_VAR_github_app_private_key: ${{ secrets.GH_APP_KEY }}
+ TF_VAR_labels: '["test", "${{ github.run_id }}"]'
+
+jobs:
+ lint:
+ name: Lint
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ directory:
+ - "."
+ - "examples/full"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Lint Example
+ uses: "infinite-automations/tflint-all-in-one@v1.0.0"
+ with:
+ directory: ${{ matrix.directory }}
+
+ update-docs:
+ name: Update Docs
+ needs:
+ - lint
+ runs-on: ubuntu-latest
+ concurrency:
+ group: ${{ github.ref }}-docs
+ cancel-in-progress: false
+ outputs:
+ changed: ${{ steps.terraform-docs.outputs.num_changed > 0 }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ if: ${{ github.event_name == 'push' }}
+ - name: Checkout
+ uses: actions/checkout@v4
+ if: ${{ github.event_name == 'pull_request' }}
+ with:
+ ref: ${{ github.event.pull_request.head.ref }}
+ - name: Render terraform docs inside the README.md
+ id: terraform-docs
+ uses: terraform-docs/gh-actions@v1.0.0
+ with:
+ working-dir: .,examples/full
+ output-file: README.md
+ output-method: inject
+ git-push: ${{ github.event_name == 'pull_request' }}
+ git-commit-message: "docs(terraform): update README.md"
+ - name: Cache Docs
+ if: ${{ github.event_name == 'push' }}
+ uses: actions/cache@v3
+ with:
+ path: |
+ README.md
+ examples/full/README.md
+ key: ${{ runner.os }}-docs-${{ github.sha }}
+
+ setup-runner:
+ name: Setup Runner
+ needs:
+ - lint
+ - update-docs
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Create k8s Kind Cluster
+ uses: helm/kind-action@v1.5.0
+ with:
+ config: "~/.kube/config"
+ wait: "120s"
+ - name: Create Runners
+ uses: infinite-automations/terraform-all-in-one@v1.2.0
+ id: apply-example
+ with:
+ directory: "examples/full"
+ apply: true
+ destroy: false
+ - name: Wait For Test
+ uses: NathanFirmo/wait-for-other-job@v1.1.1
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ job: "test-runner"
+ - name: Destroy Runners
+ uses: infinite-automations/terraform-all-in-one@v1.2.0
+ with:
+ directory: "examples/full"
+ apply: false
+ destroy: true
+
+ test-runner:
+ name: Run Test Job
+ needs:
+ - lint
+ - update-docs
+ runs-on:
+ - self-hosted
+ - test
+ - ${{ github.run_id }}
+ strategy:
+ matrix:
+ image:
+ - alpine:latest
+ - ubuntu:latest
+ - debian:latest
+ container:
+ image: ${{ matrix.image }}
+ steps:
+ - name: Print Environment Information
+ run: |
+ echo "Operating System: $OSTYPE"
+ echo "Hostname: $(hostname)"
+ echo "CPU Architecture: $(uname -m)"
+ echo "Kernel Version: $(uname -r)"
+ echo
+ cat /etc/os-release
+
+ release:
+ name: Release
+ needs:
+ - update-docs
+ - test-runner
+ concurrency:
+ group: ${{ github.ref }}-release
+ cancel-in-progress: false
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Restore Cached Docs
+ if: ${{ github.event_name == 'push' }}
+ uses: actions/cache@v3
+ with:
+ path: README.md
+ key: ${{ runner.os }}-docs-${{ github.sha }}
+ - name: Semantic Release
+ uses: cycjimmy/semantic-release-action@v4
+ with:
+ dry_run: ${{ github.event_name == 'pull_request' }}
+ ci: true
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 9b8a46e..0a2bdc5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+# local dev
+/dev
+
# Local .terraform directories
**/.terraform/*
diff --git a/.terraform-docs.yml b/.terraform-docs.yml
new file mode 100644
index 0000000..1d9b0ff
--- /dev/null
+++ b/.terraform-docs.yml
@@ -0,0 +1,45 @@
+# .terraform-docs.yml
+formatter: "markdown table"
+
+sections:
+ show:
+ - header
+ - requirements
+ - providers
+ - resources
+ - inputs
+ - outputs
+ - footer
+
+content: |-
+ {{ .Header }}
+
+ ## Module Usage
+
+ ```hcl
+ {{ include "examples/full/main.tf" }}
+ ```
+
+ {{ .Requirements }}
+
+ {{ .Providers }}
+
+ {{ .Resources }}
+
+ {{ .Inputs }}
+
+ {{ .Outputs }}
+
+ {{ .Footer }}
+
+sort:
+ enabled: true
+ by: required
+
+settings:
+ anchor: true
+ default: true
+ required: true
+ type: true
+ hide-empty: true
+ indent: 2
diff --git a/README.md b/README.md
index d038116..5342a73 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,80 @@
# terraform-helm-github-actions-runner-controller
Setup the GitHub Actions Runner Controller (ARC) in an existing kubernetes cluster
+
+
+
+
+## Module Usage
+
+```hcl
+# setup actions-runner-controller
+module "actions-runner-controller" {
+ source = "../.."
+ namespace = "github-actions-runner-controller"
+ create_namespace = true
+ allow_granting_container_mode_permissions = false
+ github_app_id = var.github_app_id
+ github_app_install_id = var.github_app_install_id
+ github_app_private_key = var.github_app_private_key
+ kubernetes_secret_name = "github-auth-secret"
+ helm_deployment_name = "actions-runner-controller"
+ helm_chart_version = "0.23.5"
+ replicas = 1
+ atomic = true
+ timeout = 600
+ depends_on = [
+ helm_release.cert_manager
+ ]
+}
+```
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 0.13 |
+| [helm](#requirement\_helm) | >= 2.11.0 |
+| [kubernetes](#requirement\_kubernetes) | >= 2.23.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [helm](#provider\_helm) | >= 2.11.0 |
+| [kubernetes](#provider\_kubernetes) | >= 2.23.0 |
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [helm_release.this](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
+| [kubernetes_namespace.this](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
+| [kubernetes_secret.this](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [github\_app\_id](#input\_github\_app\_id) | GitHub App ID | `string` | n/a | yes |
+| [github\_app\_install\_id](#input\_github\_app\_install\_id) | GitHub App Install ID | `string` | n/a | yes |
+| [github\_app\_private\_key](#input\_github\_app\_private\_key) | GitHub App Private Key | `string` | n/a | yes |
+| [allow\_granting\_container\_mode\_permissions](#input\_allow\_granting\_container\_mode\_permissions) | If true, the runner controller will be allowed to grant container mode permissions | `bool` | `false` | no |
+| [atomic](#input\_atomic) | If true, installation process purges chart on fail. If false, installation process deletes resources created by chart, but not purge them | `bool` | `true` | no |
+| [create\_namespace](#input\_create\_namespace) | If true, the namespace will be created | `bool` | `true` | no |
+| [helm\_chart\_version](#input\_helm\_chart\_version) | The version of the helm chart to deploy | `string` | `"0.23.5"` | no |
+| [helm\_deployment\_name](#input\_helm\_deployment\_name) | The name of the helm deployment | `string` | `"actions-runner-controller"` | no |
+| [kubernetes\_secret\_name](#input\_kubernetes\_secret\_name) | The name of the secret to create | `string` | `"github-auth-secret"` | no |
+| [namespace](#input\_namespace) | The namespace to deploy the runner controller into | `string` | `"github-actions-runner-controller"` | no |
+| [replicas](#input\_replicas) | The number of replicas for the runner controller | `number` | `3` | no |
+| [timeout](#input\_timeout) | Time in seconds to wait for helm deployment operation (like Jobs for hooks) | `number` | `600` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [helm\_deployment\_name](#output\_helm\_deployment\_name) | The name of the helm deployment |
+| [namespace](#output\_namespace) | The namespace runner controller was deployed into |
+| [secret\_name](#output\_secret\_name) | The name of the secret created |
+
+
+
\ No newline at end of file
diff --git a/examples/full/.terraform-docs.yml b/examples/full/.terraform-docs.yml
new file mode 100644
index 0000000..441c370
--- /dev/null
+++ b/examples/full/.terraform-docs.yml
@@ -0,0 +1,57 @@
+# .terraform-docs.yml
+formatter: "markdown table"
+
+sections:
+ show:
+ - header
+ - requirements
+ - providers
+ - resources
+ - inputs
+ - outputs
+ - footer
+
+content: |-
+ {{ .Header }}
+
+ ## 1. Setup Cert Manager
+
+ ```hcl
+ {{ include "cert-manager.tf" }}
+ ```
+
+ ## 2. Setup Agents Runner Controller
+
+ ```hcl
+ {{ include "main.tf" }}
+ ```
+
+ ## 3. Setup Runner
+
+ ```hcl
+ {{ include "runner.tf" }}
+ ```
+
+ {{ .Requirements }}
+
+ {{ .Providers }}
+
+ {{ .Resources }}
+
+ {{ .Inputs }}
+
+ {{ .Outputs }}
+
+ {{ .Footer }}
+
+sort:
+ enabled: true
+ by: required
+
+settings:
+ anchor: true
+ default: true
+ required: true
+ type: true
+ hide-empty: true
+ indent: 2
diff --git a/examples/full/.terraform.lock.hcl b/examples/full/.terraform.lock.hcl
new file mode 100644
index 0000000..9bb41bf
--- /dev/null
+++ b/examples/full/.terraform.lock.hcl
@@ -0,0 +1,59 @@
+# This file is maintained automatically by "terraform init".
+# Manual edits may be lost in future updates.
+
+provider "registry.terraform.io/gavinbunney/kubectl" {
+ version = "1.14.0"
+ constraints = ">= 1.14.0"
+ hashes = [
+ "h1:gLFn+RvP37sVzp9qnFCwngRjjFV649r6apjxvJ1E/SE=",
+ "zh:0350f3122ff711984bbc36f6093c1fe19043173fad5a904bce27f86afe3cc858",
+ "zh:07ca36c7aa7533e8325b38232c77c04d6ef1081cb0bac9d56e8ccd51f12f2030",
+ "zh:0c351afd91d9e994a71fe64bbd1662d0024006b3493bb61d46c23ea3e42a7cf5",
+ "zh:39f1a0aa1d589a7e815b62b5aa11041040903b061672c4cfc7de38622866cbc4",
+ "zh:428d3a321043b78e23c91a8d641f2d08d6b97f74c195c654f04d2c455e017de5",
+ "zh:4baf5b1de2dfe9968cc0f57fd4be5a741deb5b34ee0989519267697af5f3eee5",
+ "zh:6131a927f9dffa014ab5ca5364ac965fe9b19830d2bbf916a5b2865b956fdfcf",
+ "zh:c62e0c9fd052cbf68c5c2612af4f6408c61c7e37b615dc347918d2442dd05e93",
+ "zh:f0beffd7ce78f49ead612e4b1aefb7cb6a461d040428f514f4f9cc4e5698ac65",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/helm" {
+ version = "2.12.1"
+ constraints = ">= 2.11.0"
+ hashes = [
+ "h1:sgYI7lwGqJqPopY3NGmhb1eQ0YbH8PIXaAZAmnJrAvw=",
+ "zh:1d623fb1662703f2feb7860e3c795d849c77640eecbc5a776784d08807b15004",
+ "zh:253a5bc62ba2c4314875139e3fbd2feaad5ef6b0fb420302a474ab49e8e51a38",
+ "zh:282358f4ad4f20d0ccaab670b8645228bfad1c03ac0d0df5889f0aea8aeac01a",
+ "zh:4fd06af3091a382b3f0d8f0a60880f59640d2b6d9d6a31f9a873c6f1bde1ec50",
+ "zh:6816976b1830f5629ae279569175e88b497abbbac30ee809948a1f923c67a80d",
+ "zh:7d82c4150cdbf48cfeec867be94c7b9bd7682474d4df0ebb7e24e148f964844f",
+ "zh:83f062049eea2513118a4c6054fb06c8600bac96196f25aed2cc21898ec86e93",
+ "zh:a79eec0cf4c08fca79e44033ec6e470f25ff23c3e2c7f9bc707ed7771c1072c0",
+ "zh:b2b2d904b2821a6e579910320605bc478bbef063579a23fbfdd6fcb5871b81f8",
+ "zh:e91177ca06a15487fc570cb81ecef6359aa399459ea2aa7c4f7367ba86f6fcad",
+ "zh:e976bcb82996fc4968f8382bbcb6673efb1f586bf92074058a232028d97825b1",
+ "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/kubernetes" {
+ version = "2.24.0"
+ constraints = ">= 2.23.0"
+ hashes = [
+ "h1:u9lRMCdNXcB5/WQTZVMvGhNliW2pKOzj3SOVbu9yPpg=",
+ "zh:0ed83ec390a7e75c4990ebce698f14234de2b6204ed9a01cd042bb7ea5f26564",
+ "zh:195150e4fdab259c70088528006f4604557a051e037ebe8de64e92840f27e40a",
+ "zh:1a334af55f7a74adf033eb871c9fe7e9e648b41ab84321114ef4ca0e7a34fba6",
+ "zh:1ef68c3832691de21a61bf1a4e268123f3e08850712eda0b893cac908a0d1bc1",
+ "zh:44a1c58e5a6646e62b0bad653319c245f3b635dd03554dea2707a38f553e4a52",
+ "zh:54b5b374c4386f7f05b3fe986f9cb57bde4beab3bdf6ee33444f2b9a81b8af64",
+ "zh:aa8c2687ab784b72f8cdad8d3c3673dea83b33561e7b3f2d287ef0d06ff2a9e5",
+ "zh:e6ecba0503052ef3ad49ad56e17b2a73d9b55e30fcb82b040189d281e25e1a3b",
+ "zh:f105393f6487d3eb1f1636ba42d10c82950ddfef852244c1bca8d526fa23a9a3",
+ "zh:f17a8f1914ec66d80ccacecd40123362cf093abee3d3aa1ff9f8f687d8736f85",
+ "zh:f394b12ef01fa0bdf666a43ad152eb3890134f35e635ea056b18771c292de46e",
+ "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
+ ]
+}
diff --git a/examples/full/README.md b/examples/full/README.md
new file mode 100644
index 0000000..644b76b
--- /dev/null
+++ b/examples/full/README.md
@@ -0,0 +1,207 @@
+
+
+
+## 1. Setup Cert Manager
+
+```hcl
+# create namespace for cert mananger
+resource "kubernetes_namespace" "cert_manager" {
+ metadata {
+ labels = {
+ "name" = "cert-manager"
+ }
+ name = "cert-manager"
+ }
+}
+
+# install cert-manager helm chart using terraform
+resource "helm_release" "cert_manager" {
+ name = "cert-manager"
+ repository = "https://charts.jetstack.io"
+ chart = "cert-manager"
+ version = "v1.12.3"
+ namespace = kubernetes_namespace.cert_manager.metadata.0.name
+ atomic = true
+ timeout = 600
+ set {
+ name = "installCRDs"
+ value = "true"
+ }
+}
+```
+
+## 2. Setup Agents Runner Controller
+
+```hcl
+# setup actions-runner-controller
+module "actions-runner-controller" {
+ source = "../.."
+ namespace = "github-actions-runner-controller"
+ create_namespace = true
+ allow_granting_container_mode_permissions = false
+ github_app_id = var.github_app_id
+ github_app_install_id = var.github_app_install_id
+ github_app_private_key = var.github_app_private_key
+ kubernetes_secret_name = "github-auth-secret"
+ helm_deployment_name = "actions-runner-controller"
+ helm_chart_version = "0.23.5"
+ replicas = 1
+ atomic = true
+ timeout = 600
+ depends_on = [
+ helm_release.cert_manager
+ ]
+}
+```
+
+## 3. Setup Runner
+
+```hcl
+# create runner
+resource "kubernetes_service_account" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+ secret {
+ name = kubernetes_secret.runner.metadata.0.name
+ }
+}
+
+resource "kubernetes_secret" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+}
+
+resource "kubernetes_role" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+
+ rule {
+ api_groups = [""]
+ resources = ["pods"]
+ verbs = ["get", "list", "create", "delete"]
+ }
+ rule {
+ api_groups = [""]
+ resources = ["pods/exec"]
+ verbs = ["get", "create"]
+ }
+ rule {
+ api_groups = [""]
+ resources = ["pods/log"]
+ verbs = ["get", "list", "watch"]
+ }
+ rule {
+ api_groups = ["batch"]
+ resources = ["jobs"]
+ verbs = ["get", "list", "create", "delete"]
+ }
+ rule {
+ api_groups = [""]
+ resources = ["secrets"]
+ verbs = ["create", "delete", "get", "list"]
+ }
+}
+
+resource "kubernetes_role_binding" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+ role_ref {
+ api_group = "rbac.authorization.k8s.io"
+ kind = "Role"
+ name = "test-runner"
+ }
+ subject {
+ kind = "ServiceAccount"
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+}
+
+resource "kubectl_manifest" "runner" {
+ yaml_body = yamlencode({
+ apiVersion = "actions.summerwind.dev/v1alpha1"
+ kind = "RunnerDeployment"
+ metadata = {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+ spec = {
+ replicas = 2
+ template = {
+ spec = {
+ repository = "infinite-automations/terraform-helm-github-actions-runner-controller"
+ labels = var.labels
+ serviceAccountName = kubernetes_service_account.runner.metadata.0.name
+ containerMode = "kubernetes"
+ workVolumeClaimTemplate = {
+ storageClassName = "standard"
+ accessModes = [
+ "ReadWriteOnce"
+ ]
+ resources = {
+ requests = {
+ storage = "100Mi"
+ }
+ }
+ }
+ }
+ }
+ }
+ })
+ depends_on = [
+ module.actions-runner-controller,
+ kubernetes_service_account.runner
+ ]
+}
+```
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 0.13 |
+| [helm](#requirement\_helm) | >= 2.11.0 |
+| [kubectl](#requirement\_kubectl) | >= 1.14.0 |
+| [kubernetes](#requirement\_kubernetes) | >= 2.23.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [helm](#provider\_helm) | 2.12.1 |
+| [kubectl](#provider\_kubectl) | 1.14.0 |
+| [kubernetes](#provider\_kubernetes) | 2.24.0 |
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [helm_release.cert_manager](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
+| [kubectl_manifest.runner](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource |
+| [kubernetes_namespace.cert_manager](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
+| [kubernetes_role.runner](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/role) | resource |
+| [kubernetes_role_binding.runner](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/role_binding) | resource |
+| [kubernetes_secret.runner](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
+| [kubernetes_service_account.runner](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service_account) | resource |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [github\_app\_id](#input\_github\_app\_id) | GitHub App ID | `string` | n/a | yes |
+| [github\_app\_install\_id](#input\_github\_app\_install\_id) | GitHub App Install ID | `string` | n/a | yes |
+| [github\_app\_private\_key](#input\_github\_app\_private\_key) | GitHub App Private Key | `string` | n/a | yes |
+| [labels](#input\_labels) | The labels for the runner | `list(string)` | n/a | yes |
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/full/backend.tf b/examples/full/backend.tf
new file mode 100644
index 0000000..e6a0e2e
--- /dev/null
+++ b/examples/full/backend.tf
@@ -0,0 +1,5 @@
+
+terraform {
+ backend "local" {
+ }
+}
diff --git a/examples/full/cert-manager.tf b/examples/full/cert-manager.tf
new file mode 100644
index 0000000..6d6c182
--- /dev/null
+++ b/examples/full/cert-manager.tf
@@ -0,0 +1,24 @@
+# create namespace for cert mananger
+resource "kubernetes_namespace" "cert_manager" {
+ metadata {
+ labels = {
+ "name" = "cert-manager"
+ }
+ name = "cert-manager"
+ }
+}
+
+# install cert-manager helm chart using terraform
+resource "helm_release" "cert_manager" {
+ name = "cert-manager"
+ repository = "https://charts.jetstack.io"
+ chart = "cert-manager"
+ version = "v1.12.3"
+ namespace = kubernetes_namespace.cert_manager.metadata[0].name
+ atomic = true
+ timeout = 600
+ set {
+ name = "installCRDs"
+ value = "true"
+ }
+}
diff --git a/examples/full/main.tf b/examples/full/main.tf
new file mode 100644
index 0000000..e016d5e
--- /dev/null
+++ b/examples/full/main.tf
@@ -0,0 +1,19 @@
+# setup actions-runner-controller
+module "actions-runner-controller" {
+ source = "../.."
+ namespace = "github-actions-runner-controller"
+ create_namespace = true
+ allow_granting_container_mode_permissions = false
+ github_app_id = var.github_app_id
+ github_app_install_id = var.github_app_install_id
+ github_app_private_key = var.github_app_private_key
+ kubernetes_secret_name = "github-auth-secret"
+ helm_deployment_name = "actions-runner-controller"
+ helm_chart_version = "0.23.5"
+ replicas = 1
+ atomic = true
+ timeout = 600
+ depends_on = [
+ helm_release.cert_manager
+ ]
+}
diff --git a/examples/full/providers.tf b/examples/full/providers.tf
new file mode 100644
index 0000000..7b2baac
--- /dev/null
+++ b/examples/full/providers.tf
@@ -0,0 +1,15 @@
+provider "kubernetes" {
+ config_path = "~/.kube/config"
+}
+
+provider "helm" {
+ kubernetes {
+ config_path = "~/.kube/config"
+ }
+}
+
+provider "kubectl" {
+ config_path = "~/.kube/config"
+ load_config_file = true
+ apply_retry_count = 3
+}
diff --git a/examples/full/runner.tf b/examples/full/runner.tf
new file mode 100644
index 0000000..4464a1e
--- /dev/null
+++ b/examples/full/runner.tf
@@ -0,0 +1,104 @@
+# create runner
+resource "kubernetes_service_account" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+ secret {
+ name = kubernetes_secret.runner.metadata[0].name
+ }
+}
+
+resource "kubernetes_secret" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+}
+
+resource "kubernetes_role" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+
+ rule {
+ api_groups = [""]
+ resources = ["pods"]
+ verbs = ["get", "list", "create", "delete"]
+ }
+ rule {
+ api_groups = [""]
+ resources = ["pods/exec"]
+ verbs = ["get", "create"]
+ }
+ rule {
+ api_groups = [""]
+ resources = ["pods/log"]
+ verbs = ["get", "list", "watch"]
+ }
+ rule {
+ api_groups = ["batch"]
+ resources = ["jobs"]
+ verbs = ["get", "list", "create", "delete"]
+ }
+ rule {
+ api_groups = [""]
+ resources = ["secrets"]
+ verbs = ["create", "delete", "get", "list"]
+ }
+}
+
+resource "kubernetes_role_binding" "runner" {
+ metadata {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+ role_ref {
+ api_group = "rbac.authorization.k8s.io"
+ kind = "Role"
+ name = "test-runner"
+ }
+ subject {
+ kind = "ServiceAccount"
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+}
+
+resource "kubectl_manifest" "runner" {
+ yaml_body = yamlencode({
+ apiVersion = "actions.summerwind.dev/v1alpha1"
+ kind = "RunnerDeployment"
+ metadata = {
+ name = "test-runner"
+ namespace = module.actions-runner-controller.namespace
+ }
+ spec = {
+ replicas = 2
+ template = {
+ spec = {
+ repository = "infinite-automations/terraform-helm-github-actions-runner-controller"
+ labels = var.labels
+ serviceAccountName = kubernetes_service_account.runner.metadata[0].name
+ containerMode = "kubernetes"
+ workVolumeClaimTemplate = {
+ storageClassName = "standard"
+ accessModes = [
+ "ReadWriteOnce"
+ ]
+ resources = {
+ requests = {
+ storage = "100Mi"
+ }
+ }
+ }
+ }
+ }
+ }
+ })
+ depends_on = [
+ module.actions-runner-controller,
+ kubernetes_service_account.runner
+ ]
+}
diff --git a/examples/full/variables.tf b/examples/full/variables.tf
new file mode 100644
index 0000000..6811cf3
--- /dev/null
+++ b/examples/full/variables.tf
@@ -0,0 +1,22 @@
+variable "github_app_id" {
+ type = string
+ description = "GitHub App ID"
+ sensitive = true
+}
+
+variable "github_app_install_id" {
+ type = string
+ description = "GitHub App Install ID"
+ sensitive = true
+}
+
+variable "github_app_private_key" {
+ type = string
+ description = "GitHub App Private Key"
+ sensitive = true
+}
+
+variable "labels" {
+ type = list(string)
+ description = "The labels for the runner"
+}
diff --git a/examples/full/versions.tf b/examples/full/versions.tf
new file mode 100644
index 0000000..8b3c938
--- /dev/null
+++ b/examples/full/versions.tf
@@ -0,0 +1,17 @@
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ kubernetes = {
+ source = "hashicorp/kubernetes"
+ version = ">= 2.23.0"
+ }
+ helm = {
+ source = "hashicorp/helm"
+ version = ">= 2.11.0"
+ }
+ kubectl = {
+ source = "gavinbunney/kubectl"
+ version = ">= 1.14.0"
+ }
+ }
+}
diff --git a/main.tf b/main.tf
new file mode 100644
index 0000000..2a90475
--- /dev/null
+++ b/main.tf
@@ -0,0 +1,52 @@
+locals {
+ namespace = var.create_namespace ? kubernetes_namespace.this[0].metadata[0].name : data.kubernetes_namespace.this[0].metadata[0].name
+}
+
+data "kubernetes_namespace" "this" {
+ count = var.create_namespace ? 0 : 1
+ metadata {
+ name = var.namespace
+ }
+}
+
+resource "kubernetes_namespace" "this" {
+ count = var.create_namespace ? 1 : 0
+ metadata {
+ name = var.namespace
+ }
+}
+
+resource "kubernetes_secret" "this" {
+ metadata {
+ name = var.kubernetes_secret_name
+ namespace = local.namespace
+ }
+
+ data = {
+ github_app_id = var.github_app_id
+ github_app_installation_id = var.github_app_install_id
+ github_app_private_key = var.github_app_private_key
+ }
+}
+
+resource "helm_release" "this" {
+ name = var.helm_deployment_name
+ repository = "https://actions-runner-controller.github.io/actions-runner-controller"
+ chart = "actions-runner-controller"
+ version = var.helm_chart_version
+ namespace = local.namespace
+
+ atomic = var.atomic
+ timeout = var.timeout
+
+ values = [yamlencode({
+ replicaCount = var.replicas
+ authSecret = {
+ name = kubernetes_secret.this.metadata[0].name
+ create = false
+ }
+ rbac = {
+ allowGrantingKubernetesContainerModePermissions = var.allow_granting_container_mode_permissions
+ }
+ })]
+}
diff --git a/outputs.tf b/outputs.tf
new file mode 100644
index 0000000..da22710
--- /dev/null
+++ b/outputs.tf
@@ -0,0 +1,14 @@
+output "namespace" {
+ value = local.namespace
+ description = "The namespace runner controller was deployed into"
+}
+
+output "secret_name" {
+ value = kubernetes_secret.this.metadata[0].name
+ description = "The name of the secret created"
+}
+
+output "helm_deployment_name" {
+ value = helm_release.this.metadata[0].name
+ description = "The name of the helm deployment"
+}
diff --git a/variables.tf b/variables.tf
new file mode 100644
index 0000000..0365a86
--- /dev/null
+++ b/variables.tf
@@ -0,0 +1,71 @@
+variable "namespace" {
+ type = string
+ description = "The namespace to deploy the runner controller into"
+ default = "github-actions-runner-controller"
+}
+
+variable "create_namespace" {
+ type = bool
+ description = "If true, the namespace will be created"
+ default = true
+}
+
+variable "allow_granting_container_mode_permissions" {
+ type = bool
+ description = "If true, the runner controller will be allowed to grant container mode permissions"
+ default = false
+}
+
+variable "github_app_id" {
+ type = string
+ description = "GitHub App ID"
+ sensitive = true
+}
+
+variable "github_app_install_id" {
+ type = string
+ description = "GitHub App Install ID"
+ sensitive = true
+}
+
+variable "github_app_private_key" {
+ type = string
+ description = "GitHub App Private Key"
+ sensitive = true
+}
+
+variable "kubernetes_secret_name" {
+ type = string
+ description = "The name of the secret to create"
+ default = "github-auth-secret"
+}
+
+variable "helm_deployment_name" {
+ type = string
+ description = "The name of the helm deployment"
+ default = "actions-runner-controller"
+}
+
+variable "helm_chart_version" {
+ type = string
+ description = "The version of the helm chart to deploy"
+ default = "0.23.5"
+}
+
+variable "replicas" {
+ type = number
+ description = "The number of replicas for the runner controller"
+ default = 3
+}
+
+variable "atomic" {
+ type = bool
+ description = "If true, installation process purges chart on fail. If false, installation process deletes resources created by chart, but not purge them"
+ default = true
+}
+
+variable "timeout" {
+ type = number
+ description = "Time in seconds to wait for helm deployment operation (like Jobs for hooks)"
+ default = 600
+}
diff --git a/versions.tf b/versions.tf
new file mode 100644
index 0000000..2f4493d
--- /dev/null
+++ b/versions.tf
@@ -0,0 +1,13 @@
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ kubernetes = {
+ source = "hashicorp/kubernetes"
+ version = ">= 2.23.0"
+ }
+ helm = {
+ source = "hashicorp/helm"
+ version = ">= 2.11.0"
+ }
+ }
+}