Create Terraform Module #91
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This workflow runs manually. | |
# | |
# `Create Terraform Module` job run Terraform Cloud API call to retrieve the workspace id. | |
# It then uses API calls to find the variable ID and value. After several validations, it | |
# updates the variable in Terraform Cloud using an API call. | |
# | |
# Finally, it uses `checkout` to download the content of the repository. It runs | |
# `hashicorp/tfc-workflows-github/actions/upload-configuration` to creates a configuration version | |
# and uploads the directory containing files for a specified Terraform Cloud Workspace. Then, it | |
# performs an API driven run in Terraform Cloud, using a configuration version and the workspace's | |
# current variables. | |
# | |
# Documentation | |
# - https://github.com/actions/checkout | |
# - https://github.com/hashicorp/tfc-workflows-github/tree/main/actions/upload-configuration | |
# - https://github.com/hashicorp/tfc-workflows-github/tree/main/actions/create-run | |
# | |
# Prerequisites: | |
# - A Terraform Cloud workspace | |
# - A Terraform Cloud API token with required permissions | |
# | |
# Terraform Cloud user API token stored as a GitHub secret (e.g. TF_API_TOKEN) in the repository. | |
# Documentation: | |
# - https://www.terraform.io/docs/cloud/users-teams-organizations/api-tokens.html | |
# - https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets | |
name: "Create Terraform Module" | |
on: # yamllint disable-line rule:truthy | |
workflow_dispatch: | |
inputs: | |
module_name: | |
description: The name of the module to create. Module name must use a three-part name format like `terraform-<PROVIDER>-<NAME>` and contain only alphanumeric and hypens. | |
required: true | |
type: string | |
jobs: | |
job: | |
name: Create Terraform Module | |
runs-on: ubuntu-latest | |
env: | |
TF_API_TOKEN: ${{ secrets.TFC_API_TOKEN }} | |
TF_CLOUD_ORGANIZATION: ConseilsTI | |
TF_VARIABLE: module_names | |
steps: | |
- name: Get workspace ID | |
id: get_workspace_id | |
env: | |
EVENT_CONTEXT: ${{ toJSON(github.event) }} | |
run: | | |
echo "INFO | Building required variables." | |
workspace_name=$(echo "${EVENT_CONTEXT}" | jq -r ".repository.name") | |
workspace_name="${workspace_name,,}" | |
echo "workspace_name=${workspace_name}" >> "${GITHUB_OUTPUT}" | |
echo "INFO | Workspace name: ${workspace_name}" | |
tfc_api_url="https://app.terraform.io/api/v2" | |
auth_header="Authorization: Bearer ${TF_API_TOKEN}" | |
content_header="Content-Type: application/vnd.api+json" | |
echo "INFO | Running API call to get workspace ID." | |
workspace_id=$(curl -sS -H "${auth_header}" -H "${content_header}" -L "${tfc_api_url}/organizations/${{ env.TF_CLOUD_ORGANIZATION }}/workspaces/${workspace_name}" | jq -r '.data."id"') | |
if [[ "${workspace_id}" != "null" ]]; then | |
echo "INFO | Workspace ID: ${workspace_id}" | |
echo "workspace_id=${workspace_id}" >> "${GITHUB_OUTPUT}" | |
else | |
echo "ERROR | Unable to get workspace ID." | |
exit 1 | |
fi | |
- name: Get variable | |
id: get_variable | |
run: | | |
echo "INFO | Building required variables." | |
tfc_api_url="https://app.terraform.io/api/v2" | |
auth_header="Authorization: Bearer ${TF_API_TOKEN}" | |
content_header="Content-Type: application/vnd.api+json" | |
echo "INFO | Running API call to get variable id." | |
variable_id=$(curl -sS -H "${auth_header}" -H "${content_header}" -L "${tfc_api_url}/workspaces/${{ steps.get_workspace_id.outputs.workspace_id }}/vars" | jq '.data[] | select(.attributes.key == "${{ env.TF_VARIABLE }}" ) | .id') | |
if [[ "${variable_id}" != "null" ]]; then | |
echo "INFO | Variable ID: ${variable_id}" | |
echo "variable_id=${variable_id}" >> "${GITHUB_OUTPUT}" | |
else | |
echo "ERROR | Unable to get variable id." | |
exit 1 | |
fi | |
echo "INFO | Running API call to get variable value." | |
variable_value=$(curl -sS -H "${auth_header}" -H "${content_header}" -L "${tfc_api_url}/workspaces/${{ steps.get_workspace_id.outputs.workspace_id }}/vars" | jq '.data[] | select(.attributes.key == "${{ env.TF_VARIABLE }}" ) | .attributes.value') | |
if [[ "${variable_value}" != "null" ]]; then | |
echo "INFO | Variable value: ${variable_value}" | |
echo "variable_value=${variable_value}" >> "${GITHUB_OUTPUT}" | |
else | |
echo "ERROR | Unable to get variable value." | |
exit 1 | |
fi | |
- name: Update variable | |
run: | | |
echo "INFO | Building required variables." | |
tfc_api_url="https://app.terraform.io/api/v2" | |
auth_header="Authorization: Bearer ${TF_API_TOKEN}" | |
content_header="Content-Type: application/vnd.api+json" | |
variable_value=$(echo -e "${{ steps.get_variable.outputs.variable_value }}") | |
if [[ "${{ github.event.inputs.module_name }}" =~ ^terraform-[a-zA-Z]+-[a-zA-Z0-9-]+$ ]]; then | |
echo "INFO | Module's name use a three-part name format like \"terraform-<PROVIDER>-<NAME>\" and contain only alphanumeric and hypens." | |
else | |
echo "ERROR | Module's name must use a three-part name format like \"terraform-<PROVIDER>-<NAME>\" and contain only alphanumeric and hypens." | |
exit 1 | |
fi | |
if [[ "${variable_value}" =~ ^\[.*\]$ ]]; then | |
echo "INFO | Variable is an array." | |
else | |
echo "ERROR | Variable is not an array." | |
exit 1 | |
fi | |
if [[ "${variable_value}" =~ "${{ github.event.inputs.module_name }}" ]]; then | |
echo "ERROR | Module's name is already in use." | |
exit 1 | |
fi | |
echo "INFO | Adding new module's name into the array." | |
variable_value="${variable_value::-1}, \"${{ github.event.inputs.module_name }}\"]" | |
printf 'INFO | Converting \\" into \\\\".' | |
variable_value=${variable_value//\"/\\\"} | |
echo "INFO | Building JSON payload." | |
json_string='{"data":{"id":"'"${{ steps.get_variable.outputs.variable_id }}"'","attributes":{"value":"'"${variable_value}"'"},"type":"vars"}}' | |
json_payload=$(echo "${json_string}" | jq) | |
echo "INFO | Running API call to update variable." | |
{ | |
run=$(curl -sS --request PATCH --url "${tfc_api_url}/vars/${{ steps.get_variable.outputs.variable_id }}" \ | |
--header "${auth_header}" --header "${content_header}" --data "${json_payload}") | |
if ! [[ "${run}" =~ "{\"data\":" ]]; then | |
echo "ERROR | Unable to update variable." | |
echo "${run}" | |
exit 1 | |
else | |
echo "INFO | Variable updated." | |
fi | |
} || | |
{ | |
echo "ERROR | Unable to update variable." | |
exit 1 | |
} | |
- uses: actions/checkout@v4 | |
- uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.2.0 | |
id: upload | |
with: | |
workspace: ${{ steps.get_workspace_id.outputs.workspace_name }} | |
directory: ./ | |
- uses: hashicorp/tfc-workflows-github/actions/create-run@v1.2.0 | |
id: create-run | |
with: | |
workspace: ${{ steps.get_workspace_id.outputs.workspace_name }} | |
configuration_version: ${{ steps.upload.outputs.configuration_version_id }} |