{"id":23590932,"url":"https://github.com/utilitywarehouse/terraform-applier","last_synced_at":"2025-05-07T16:21:04.569Z","repository":{"id":35693683,"uuid":"212313505","full_name":"utilitywarehouse/terraform-applier","owner":"utilitywarehouse","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-01T12:05:32.000Z","size":2065,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-01T13:22:23.137Z","etag":null,"topics":["gitops","system","uw-dep-alpine","uw-dep-gitsync","uw-dep-go","uw-dep-strongbox","uw-owner-system"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/utilitywarehouse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-10-02T10:42:43.000Z","updated_at":"2025-05-01T12:05:35.000Z","dependencies_parsed_at":"2023-09-22T20:45:31.754Z","dependency_job_id":"208e8692-d5cd-4c22-b6e5-e86f919ca3e3","html_url":"https://github.com/utilitywarehouse/terraform-applier","commit_stats":null,"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilitywarehouse%2Fterraform-applier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilitywarehouse%2Fterraform-applier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilitywarehouse%2Fterraform-applier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilitywarehouse%2Fterraform-applier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/utilitywarehouse","download_url":"https://codeload.github.com/utilitywarehouse/terraform-applier/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252913056,"owners_count":21824092,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gitops","system","uw-dep-alpine","uw-dep-gitsync","uw-dep-go","uw-dep-strongbox","uw-owner-system"],"created_at":"2024-12-27T07:16:56.132Z","updated_at":"2025-05-07T16:21:04.549Z","avatar_url":"https://github.com/utilitywarehouse.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# terraform-applier\n\nHeavily adapted from\n[kube-applier](https://github.com/utilitywarehouse/kube-applier),\nterraform-applier enables continuous deployment of Terraform code by applying\nmodules from a Git repository.\n\n## Usage\n\n### Module CRD\n\nTerraform-applier module's run behaviour is controlled through the Module CRD. Refer to the code\nor CRD yaml definition for details, an example with the default values is shown\nbelow:\n\n```yaml\napiVersion: terraform-applier.uw.systems/v1beta1\nkind: Module\nmetadata:\n  name: hello\nspec:\n  repoURL: git@github.com:utilitywarehouse/terraform-applier.git\n  repoRef: master\n  path: dev/hello\n  schedule: \"00 */1 * * *\"\n  planOnly: false\n  pollInterval: 60\n  runTimeout: 900\n  delegateServiceAccountSecretRef: terraform-applier-delegate-token\n  rbac:\n    - role: Admin\n      subjects:\n        - name: user@email.com\n          kind: User\n        - name: some_group_name\n          kind: Group\n  backend:\n    - name: bucket\n      value: dev-terraform-state\n    - name: region\n      value: eu-west-1\n    - name: key\n      valueFrom:\n        configMapKeyRef:\n          name: hello-module-config\n          key: bucket_key\n  env:\n    - name: AWS_REGION\n      value: eu-west-1\n    - name: \"AWS_SECRET_ACCESS_KEY\"\n      valueFrom:\n        secretKeyRef:\n          name: hello-module-secrets\n          key: AWS_SECRET_KEY\n    - name: TF_APPLIER_STRONGBOX_KEYRING\n      valueFrom:\n        secretKeyRef:\n          name: hello-module-secrets\n          key: strongbox_keyring\n  var:\n    - name: image_id\n      value: ami-abc123\n    - name: availability_zone_names\n      valueFrom:\n        configMapKeyRef:\n          name: hello-module-config\n          key: availability_zone_names\n```\n\nSee the documentation on the Module CRD\n[spec](api/v1beta1/module_types.go)\nfor more details.\n\n### Delegate ServiceAccount\n\nTo minimize access required by controller on other namespaces, the concept of a\ndelegate ServiceAccount is introduced. When fetching secrets and configmaps for the Module, terraform-applier will use the credentials defined in the Secret referenced by\n`delegateServiceAccountSecretRef`. This is a ServiceAccount in the same\nnamespace as the Module itself and should typically be given only `GET` access to only the secrets and configmaps referenced in module CRD.\n\n### ENV and VAR\n\nThe `envs` referenced in module will be set before the terraform run. this should not be used for any well known Terraform environment variables that are already covered in options. [more info](https://pkg.go.dev/github.com/hashicorp/terraform-exec@v0.18.1/tfexec#Terraform)\n\nAll referenced `vars` will be json encoded as key-value pair and written to temp file `*.auto.tfvars.json` in module's root folder. Terraform will load these vars during `plan` and `apply`.\n\n### Terraform backend configuration\n\nuse `backend` to configure backend of the module. The key/value pair referenced in the module's `backend` will be set when initialising Terraform via `-backend-config=\"KEY=VALUE\"` flag.\nPlease note `backend` doesn't setup new backend it only configures existing backend, please see [Partial Configuration](https://developer.hashicorp.com/terraform/language/settings/backends/configuration#partial-configuration) for more info.\n\n### Private Module Source\n\nTerraform installs modules from Git repositories by running `git clone`, and so it will respect any local Git configuration set on your system, including credentials.\nTerraform applier supports SSH credentials to fetch modules from private repository. Admin can enable this by setting `--set-git-ssh-command` flag and mounting SSH key on controller (please see `Controller config`).\nonce this flag is enabled controller configures `GIT_SSH_COMMAND` env with correct private key and known-hosts file path. this env will be used by `git` to fetch private repo using SSH.\nSince only SSH auth method is supported module source URL should indicate SSH protocol as shown...\n\n```\nmodule \"consul\" {\n  source = \"git@github.com:hashicorp/example.git\"\n}\nmodule \"storage\" {\n  source = \"git::ssh://username@example.com/storage.git\"\n}\n```\n\nSince key is set on controller it can be used by ALL modules managed by the controller. Terraform applier doesn't support private key per module yet.\n\n### Strongbox decryption\n\nTerraform applier supports strongbox decryption, its triggered if \n`TF_APPLIER_STRONGBOX_KEYRING` or `TF_APPLIER_STRONGBOX_IDENTITY` EVN is set on module.\ncontent of this ENV should be valid strongbox keyring file data which should include strongbox key used to encrypt secrets in the module.\nTF Applier will also configure Git and Strongbox Home before running `init` to decrypt any encrypted file from remote terraform module as well.\n\n### RBAC\n\nTerraform applier does user authentication using OIDC flow (see Controller config).\nduring oidc flow it requests `openid, email, groups` scopes to get user's email and groups info as part of `id_token`.\n`rbac` section of module crd can be use to set list of Admins who's allowed to do `force run`.\n\n```\nrbac:\n- role: Admin\n  subjects:\n  - name: user@email.com\n    kind: User\n  - name: some_group_name\n    kind: Group\n```\n\nAt the moment only \"Admin\" role is supported, value of subjects can be either `email address` of users as kind `User` or the group name as kind `Group`.\n\n**If `OIDC Issuer` is not set then web server will skip authentication and all `force run` requests will be allowed.**\n\n### Graceful shutdown\n\nTo make sure all terraform module run does complete in finite time `runTimeout` is added to the module spec.\ndefault value is `900s` and MAX value is `1800s`. Terraform run `(init,plan and apply if required)` should finish in this time otherwise it will be forced shutdown.\n\nIf controller received TERM signal during a module run, then it will try and finish current stage of the run (either `init`, `plan` or `apply`) without the force shutdown. during this case it will not process next stage. eg. if TERM signal received during `plan` stage then\nit will not do `apply` even if drift is detected.\n\nController will force shutdown on current stage run if it takes more time then `TERMINATION_GRACE_PERIOD` set on controller.\n\n### Git Sync\n\nTerraform-applier uses [git-mirror](https://github.com/utilitywarehouse/git-mirror) package to sync git repositories.\nThis package supports mirroring multiple repositories and all available references.\nBecause of this terraform-applier can also support different revisions on same repo. it can be set in module CRD by `repoRef` field.\nUse following config to add repositories. supported urls formats are\n'git@host.xz:org/repo.git','ssh://git@host.xz/org/repo.git' or 'https://host.xz/org/repo.git'\n\n```yaml\ngit_mirror:\n  defaults:\n    interval: 1m # defaults to 30s\n    git_gc: always # defaults to always\n    auth:\n      ssh_key_path: /etc/git-secret/ssh # defaults to --git-ssh-key-file flag\n      ssh_known_hosts_path: /etc/git-secret/known_hosts # defaults to --git-ssh-known-hosts\n  repositories:\n    - remote: git@github.com:utilitywarehouse/terraform-applier.git\n    - remote: git@github.com:utilitywarehouse/other-repo.git\n```\n\n### Git PR Planner\n\nTerraform-applier can run terraform plan for open Pull Requests and post plan run outputs as PR comments.\nTo enable that, terraform-applier does the following:\n\n1. Receives a webhook from Github notifying about a change in open Pull Requests e.g. new PR created, new commit pushed, new comment posted, etc.\n2. Requests more information from Github about the PR: list of commits, comments, files updated, etc.\n3. If plan run needs to be executed due to new commit or user request via comments e.g. `@terraform-applier plan \u003cmodule name\u003e`, the request gets verified and forwarded to the Terraform Runner\n4. The run output gets posted to the PR comments as soon as run is finished and stored in Redis\n\nApart from listening to webhooks terraform-applier also runs polling jobs at a set interval (every 10 minutes by default). These jobs help making sure no webhooks were missed and there are no outstanding requests.\n\nPR Planner feature is enabled by default, but can be disabled either for a specific module by setting `planOnPR` to `false` in the module spec, or by setting `DISABLE_PR_PLANNER` env var to `false` to be disabled entirely across all modules.\n\n### Controller config\n\n- `--repos-root-path (REPOS_ROOT_PATH)` - (default: `/src`) Absolute path to the directory containing all repositories of the modules.\n  This dir will be cleared on start.\n- `--config (TF_APPLIER_CONFIG)` - (default: `/config/config.yaml`) Path to the tf applier config file containing repository config.\n- `--min-interval-between-runs (MIN_INTERVAL_BETWEEN_RUNS)` - (default: `60`) The minimum interval in seconds, user can set between 2 consecutive runs. This value defines the frequency of runs.\n- `--termination-grace-period (TERMINATION_GRACE_PERIOD)` - (default: `60`) Termination grace period is the ime given to\n  the running job to finish current run after 1st TERM signal is received. After this timeout runner will be forced to shutdown.\n  Ideally this timeout should be just below the `terminationGracePeriodSeconds` set on controller pod.\n- `--terraform-path (TERRAFORM_PATH)` - (default: `\"\"`) The local path to a terraform\n  binary to use.\n- `--terraform-version (TERRAFORM_VERSION)` - (default: `\"\"`) The version of terraform to\n  use. The applier will install the requested release when it starts up. If you\n  don't specify an explicit version, it will choose the latest available\n  one. Ignored if `TERRAFORM_PATH` is set.\n- `--set-git-ssh-command-global-env (SET_GIT_SSH_COMMAND_GLOBAL_ENV)` - (default: `false`) If set GIT_SSH_COMMAND env will be set as global env for all modules. This ssh command will be used by modules during terraform init to pull private remote modules.\n- `--git-ssh-key-file (GIT_SSH_KEY_FILE)` - (default: `/etc/git-secret/ssh`) The path to git ssh key which will be used to setup GIT_SSH_COMMAND env.\n- `--git-ssh-known-hosts-file (GIT_SSH_KNOWN_HOSTS_FILE)` - (default: `/etc/git-secret/known_hosts`) The local path to the known hosts file used to setup GIT_SSH_COMMAND env.\n- `--git-verify-known-hosts (GIT_VERIFY_KNOWN_HOSTS)` - (default: `true`) The local path to the known hosts file used to setup GIT_SSH_COMMAND env.\n- `--controller-runtime-env (CONTROLLER_RUNTIME_ENV)` - (default: `\"\"`) The comma separated list of ENVs which will be passed from controller to all terraform run process. The envs should be set on the controller.\n- `--cleanup-temp-dir` - (default: `false`) If set, the contents of the OS temporary directory and `/src` will be removed. This can help removing redundant terraform binaries and avoiding the directories growing in size with every restart.\n\n---\n\n- `--disable-pr-planner (DISABLE_PR_PLANNER)` - (default: `false`) Disable PR planner feature across all modules\n- `--pr-planner-interval (PR_PLANNER_INTERVAL)` - (default: `300`) The inverval at which terraform-applier polls Github for any open PRs.\n- `--pr-planner-webhook-port (PR_PLANNER_WEBHOOK_PORT)` - (default: `\":8083\"`) Port to listen to for incoming Github webhooks\n- `--github-token (GITHUB_TOKEN)` - (default: `\"\"`) Github API personal access token that allows requesting information about open Pull Requests and post comments to these PRs.  \n  Example permissions: `Read` access to metadata and contents, `Read and Write` access to issues, and pull requests.\n- `--github-webhook-secret (GITHUB_WEBHOOK_SECRET)` - (default: `\"\"`) User-defined secret that will be used to sign and authorise the incoming webhooks.  \n  Example Github webhook settings:\n  - Payload URL: `https://teerraform-applier.foo.bar/github-events`\n  - Content Type: `application/json`\n  - Secret: `\u003cGITHUB_WEBHOOK_SECRET\u003e`\n  - Enable SSL verification: `true`\n  - Events: `Issue comments`, `Pull requests`\n  - Active: `true`\n\n---\n\n- `--module-label-selector (MODULE_LABEL_SELECTOR)` - (default: `\"\"`) If present controller will only watch and process modules with this label.\n  Env value string should be in the form of 'label-key=label-value'. if multiple terraform-applier is running in same cluster\n  and if any 1 of them is in cluster scope mode then this env `must` be set otherwise it will watch ALL modules and interfere\n  with other controllers run.\n- `--watch-namespaces (WATCH_NAMESPACES)` - (default: `\"\"`) if set controller will only watch given namespaces for modules. it will operate\n  in namespace scope mode and controller will not need any cluster permissions. if `label selector` also set then it will\n  only watch modules with selector label in a given namespace.\n- `--leader-elect (LEADER_ELECT)` - (default: `false`) Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.\n- `--election-id (ELECTION_ID)` - (default: `auto generated`) it determines the name of the resource that leader election will use for holding the leader lock. if multiple controllers are running with same label selector and watch namespace value then they belong to same stack. if election enabled, ELECTION_ID needs to be unique per stack. If this is not unique to the stack then only one stack will be working concurrently. if not set value will be auto generated based on given label selector and watch namespace value.\n\n---\n\n- `--log-level (LOG_LEVEL)` - (default: `INFO`) `TRACE|DEBUG|INFO|WARN|ERROR`, case insensitive.\n- `--webserver-bind-address` - (default: `8080`) The address the web server binds to.\n- `--metrics-bind-address` - (default: `8081`) The address the metric endpoint binds to.\n- `--health-probe-bind-address` - (default: `8082`) The address the probe endpoint binds to.\n\n---\n\n- `(VAULT_ADDR)` - (default: `\"\"`) The Address of the Vault server expressed as a URL and port\n- `(VAULT_CACERT)` - (default: `\"\"`) The path to a PEM-encoded CA certificate file.\n- `(VAULT_CAPATH)` - (default: `\"\"`) The Path to a directory of PEM-encoded CA certificate files on the local disk.\n- `--vault-aws-secret-engine-path (VAULT_AWS_SEC_ENG_PATH)` - (default: `/aws`) The path where AWS secrets engine is enabled.\n- `--vault-gcp-secret-engine-path (VAULT_GCP_SEC_ENG_PATH)` - (default: `/gcp`) The path where GCP secrets engine is enabled.\n- `--vault-kube-auth-path (VAULT_KUBE_AUTH_PATH)` - (default: `/auth/kubernetes`) The path where kubernetes auth method is mounted.\n\n---\n\n- `--oidc-callback-url (OIDC_CALLBACK_URL)` - (default: `\"\"`) The callback url used for OIDC auth flow, this should be the terraform-applier url.\n- `--oidc-client-id (OIDC_CLIENT_ID)` - (default: `\"\"`) The client ID of the OIDC app.\n- `--oidc-client-secret (OIDC_CLIENT_SECRET)` - (default: `\"\"`) The client secret of the OIDC app.\n- `--oidc-issuer (OIDC_ISSUER)` - (default: `\"\"`) The url of the IDP where OIDC app is created.\n\n**If `OIDC Issuer` is not set then web server will skip authentication and all `force run` requests will be allowed.**\n\n## Kube backend\n\nFor modules using kubernetes backend or provider, ideally module should be using its own SA's token (terraform-applier-delegate-token) for authentication with kube cluster and not depend on default in cluster config of controller's SA but kube provider ignores `host` and `token` backend attributes if kube config is not set. [related issue](https://github.com/hashicorp/terraform/issues/31275)\n\ncontroller creates a kube config at temp location and sets `KUBE_CONFIG_PATH` ENV for the module. this generated config contains server URL as well as cluster CA cert.\nsince `KUBE_CONFIG_PATH` is already set module just need to set `namespace` and `token`. token can be passed as ENV `KUBE_TOKEN`. [doc](https://developer.hashicorp.com/terraform/language/settings/backends/kubernetes)\n\n```yaml\napiVersion: terraform-applier.uw.systems/v1beta1\nkind: Module\nmetadata:\n  name: hello-kube\nspec:\n  backend:\n    - name: namespace\n      value: sys-hello-kube\n  env:\n    - name: KUBE_TOKEN\n      valueFrom:\n        secretKeyRef:\n          name: terraform-applier-delegate-token\n          key: token\n```\n\n## Vault integration\n\nterraform-applier supports fetching (generating) secrets for AWS \u0026 GCP Secrets from the vault.\nOnly kubernetes auth method is supported using module's delegated service account's jwt (secret:terraform-applier-delegate-token) for vault login. \nFor AWS creds given `vaultRole` will be used as `authRole` and in GCP it will be name of the `roleset` or `account`.\nFor GCP only [OAuth2 access token](https://developer.hashicorp.com/vault/docs/secrets/gcp#access-tokens) is supported.\n[access-token are better then keys for frequent repetitive tasks.](https://developer.hashicorp.com/vault/docs/secrets/gcp#access-tokens-vs-service-account-keys)\n\n```yaml\nspec:\n  vaultRequests:\n    # If aws specified, controller will request AWS creds from vault and set\n    # AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN envs during\n    # terraform run.\n    aws:\n      # VaultRole Specifies the name of the vault role to generate credentials against.\n      vaultRole: dev_aws_some-vault-role\n      \n      # Must be one of iam_user, assumed_role, or federation_token.\n      credentialType: assumed_role\n      \n      # The ARN of the role to assume if credential_type on the Vault role is assumed_role.\n      # Optional if the Vault role only allows a single AWS role ARN.\n      roleARN: arn:aws:iam::00000000:role/sys-tf-applier-example\n    \n    # If gcp specified, controller will request OAuth2 access token and\n    # sets GOOGLE_OAUTH_ACCESS_TOKEN envs during terraform runs\n    # one of roleset, staticAccount or impersonatedAccount must be set\n     gcp:\n       # roleset Specifies the name of an roleset with secret type access_token \n       # to generate access_token under.\n       roleset: gcp_proj_roleset\n      \n       # staticAccount Specifies the name name of the static account with secret \n       # type access_token to generate access_token under.\n       staticAccount: gcp_proj_static-account\n      \n       # impersonatedAccount Specifies the name of the impersonated account to \n       # generate access_token under.\n       impersonatedAccount: gcp_proj_impersonate-account\n\n```\n\n### Vault CA Reload\nterraform-applier support hot reload of vault CA cert for secure communication.\nCA is updated before making vault API Calls. Following envs are supported.\n\n* `VAULT_CACERT`: value should be path to a PEM-encoded certificate file or bundle.\n  Takes precedence over CACertificate and CAPath.\n\n* `VAULT_CAPATH`: value should be path to a directory populated with PEM-encoded certificates.\n\n* `VAULT_CAURL`: value should be URL which returns a PEM-encoded certificate or bundle as body.\n   Takes precedence over CAPath.\n\n## Monitoring\n\n### Metrics\n\nterraform-applier exports Prometheus metrics. The metrics are available on given metrics port at `/metrics`.\n\nIn addition to the [controller-runtime](https://book.kubebuilder.io/reference/metrics-reference.html) default metrics, the following custom metrics are included:\n\n- `terraform_applier_module_info`- (tags: `module`,`namespace`, `state`, `reason`) A Gauge that captures the current information about module including status\n- `terraform_applier_module_run_count` - (tags: `module`,`namespace`, `run_type`, `success`) A Counter for each module that has had a terraform run attempt over the lifetime of\n  the application, incremented with each apply attempt and tagged with the result of the run (`success=true|false`)\n- `terraform_applier_module_run_duration_seconds` - (tags: `module`,`namespace`, `run_type`, `success`) A Summary that keeps track of the durations of each terraform run for\n  each module, tagged with the result of the run (`success=true|false`)\n- `terraform_applier_module_last_run_success` - (tags: `module`,`namespace`, `run_type`) A `Gauge` which\n  tracks whether the last terraform run for a module was successful.\n- `terraform_applier_module_last_run_timestamp` - (tags: `module`,`namespace`,`run_type`) A Gauge that captures the Timestamp of the last successful module run.\n- `terraform_applier_git_last_mirror_timestamp` - (tags: `repo`) A Gauge that captures the Timestamp of the last successful git sync per repo.\n- `terraform_applier_git_mirror_count` - (tags: `repo`,`success`) A Counter for each repo sync, incremented with each sync attempt and tagged with the result (`success=true|false`)\n- `terraform_applier_git_mirror_latency_seconds` - (tags: `repo`) A Summary that keeps track of the git sync latency per repo.\n\n\n## Github Actions\n\n`terraform-applier` provides github action to [trigger runs on managed modules](.github/actions/trigger-run/action.yaml).\n`action` uses kubernetes API calls to trigger runs, For authentication it uses service account\ntoken with access to the modules.\n\nThe [ci-rbac](manifests/base/ci-rbac) base can be imported in namespace to provide min required permission\nto trigger runs on any modules in the namespace.\nbase will create `terraform-applier-ci` service account and corresponding secret.\n\n\nImport `ci-rbac` base to create required sa and secret\n```yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n  - github.com/utilitywarehouse/terraform-applier//manifests/base/ci-rbac?ref=master\n```\n\nTo get the bearer token you can find the Secret in k8s. \nthis token should be added to `Repository secrets` of the repo.\n```sh\nkubectl --context \u003cenvironment\u003e -n \u003cnamespace\u003e get secrets terraform-applier-ci-token -o json | jq -r '.data.token' | base64 -d\n```\n\n### Github Workflow\n\nFollowing workflow will trigger apply run on `hello` module from `default` namespace\non push to `master` branch.\n```yaml\nname: trigger-terraform-run\n\non:\n  push:\n    branches:\n      - master\n      - main\n\njobs:\n  trigger-terraform-run:\n    runs-on: ubuntu-latest # or internal runner if k8s is on private network\n    steps:\n      - name: Trigger Terraform Apply\n        uses: utilitywarehouse/terraform-applier/.github/actions/trigger-run@master\n        env:\n          # The address and port of the Kubernetes API server (required)\n          TFA_K8S_API_SERVER: https://k8s-api-server-url\n          \n          # Bearer token for authentication to the API server (required)\n          # if ci base is used then this is the token from 'terraform-applier-ci-token' secret\n          TFA_K8S_TOKEN: ${{ secrets.K8S_TOKEN }}\n          \n          # The namespace of the module (required)\n          TFA_NAMESPACE: default\n\n          # The name of the module to trigger run (required)\n          TFA_MODULE: hello\n\n          # Type of the run to trigger valid options are 'ForcedApply' or 'ForcedPlan'.\n          # (optional) default: ForcedApply\n          TFA_RUN_TYPE: ForcedApply\n\n          # Allow insecure server connections (optional)\n          # default: false\n          TFA_INSECURE: true\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Futilitywarehouse%2Fterraform-applier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Futilitywarehouse%2Fterraform-applier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Futilitywarehouse%2Fterraform-applier/lists"}