diff --git a/.github/workflows/terraform-module-ci.yaml b/.github/workflows/terraform-module-ci.yaml index 7d9eeac..770df6b 100644 --- a/.github/workflows/terraform-module-ci.yaml +++ b/.github/workflows/terraform-module-ci.yaml @@ -30,6 +30,11 @@ on: description: "TFLint version to use for the tests." required: true type : string + readme-file-path: + description: | + "README.md file path to inject terraform docs into. Default is the root of the repository." + type : string + default: "." env: ARM_TENANT_ID: ${{ secrets.REPO_AZURE_DSB_TENANT_ID }} @@ -167,7 +172,6 @@ jobs: exit 1 fi continue-on-error: false - terraform-module-ci: name: "Terraform Test" @@ -254,12 +258,39 @@ jobs: fi continue-on-error: false + generate-docs: + name: Update README.md + needs: terraform-module-ci + runs-on: ubuntu-latest + if: needs.terraform-module-ci.result == 'success' + steps: + - name: "📥 Checkout" + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: "📝 Validate and update README.md" + id: update-readme + uses: dsb-norge/github-actions-terraform/terraform-docs@v0 + with: + readme-file-path: ${{ inputs.readme-file-path }} + continue-on-error: true + + - name: "🧐 Validation outcome: 📝 Update docs" + run: | + if [ ! "${{ steps.update-readme.outcome }}" == 'success' ]; then + echo "::error title=Update README.md failed::Outcome of update README.md step was '${{ steps.update-readme.outcome }}'!" + exit 1 + fi + continue-on-error: false + + # create a global result indicating if workflow steps succeeded or not, # handy for branch protection rules conclusion: if: always() name: "Terraform conclusion" - needs: [create-matrix, terraform-module-ci] + needs: [create-matrix, terraform-module-ci, generate-docs] runs-on: ubuntu-latest # no need to schedule this on our own runners defaults: run: diff --git a/README.md b/README.md index e97c144..853ded9 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ jobs: ```text permissions: id-token: write # Required for Azure password-less authentication - contents: read # Required for actions/checkout + contents: write # Required for actions/checkout and to update readme by PR. pull-requests: write # Required for commenting on PRs ``` @@ -216,6 +216,7 @@ jobs: - terraform-version: The version of Terraform to use for the tests (required). - tflint-version: The version of tflint (required) +- readme-file-path: path to README.md file. By default repo root used. #### Secrets @@ -259,7 +260,13 @@ Jobs: - Add validation summary as pull request comment - Validate outcomes of init and test - 3. conclusion: + 3. generate-docs: + - Steps: + - Checkout working branch + - Terraform-docs + - Validate outcome of terraform-docs + + 4. conclusion: - Steps: - Exit with status 1 if any of the previous jobs failed or were cancelled @@ -289,6 +296,7 @@ jobs: with: terraform-version: "1.9.x" tflint-version: "v0.53.0" + readme-file-path: '.' ``` ## Maintenance diff --git a/terraform-docs/action.yaml b/terraform-docs/action.yaml new file mode 100644 index 0000000..f6f1335 --- /dev/null +++ b/terraform-docs/action.yaml @@ -0,0 +1,65 @@ +name: "Run terraform docs" +description: "Inject terraform docs for modules into README.md" +author: "Artjoms Laivins" + +inputs: + readme-file-path: + description: | + "README.md file path to inject terraform docs into. Default is the root of the repository. + Path consider default name of README.md. + If README.md is in repo root then use github-workspace as path." + +runs: + using: "composite" + steps: + - id: validate-readme + shell: bash + run: | + set -o allexport; source "${{ github.action_path }}/helpers.sh"; set +o allexport; + + README_FILE="${{ inputs.readme-file-path }}/README.md" + + if [ -f "${README_FILE}" ]; then + log-info "Checking if delimiters exist in ${README_FILE}" + if grep -q '' "${README_FILE}" && grep -q '' "${README_FILE}" ; then + log-info "Delimiters exist in ${README_FILE}" + log-info "Checking if delimiters are in the correct order" + START_LINE=$(grep -n '' "${README_FILE}" | cut -d: -f1) + log-info "BEGIN_TF_DOCS found on line: $START_LINE" + END_LINE=$(grep -n '' "${README_FILE}" | cut -d: -f1) + log-info "END_TF_DOCS found on line: $END_LINE" + if [ "$START_LINE" -lt "$END_LINE" ]; then + log-info "Delimiters are in the correct order" + else + log-error "Delimiters are not in the correct order, verify ${README_FILE}" + exit 1 + fi + else + log-info "Delimiters do not exist in ${README_FILE}" + log-info "Adding delimiters to ${README_FILE}" + printf "\nBelow is a placeholder for Terraform-docs generated documentation. Do not edit between the delimiters.\n" >> "${README_FILE}" + { + echo "" + echo " " + echo "" + } >> "${README_FILE}" + log-info "Delimiters added to ${README_FILE}" + fi + + else + log-info "File ${README_FILE} does not exist. Terraform-docs will create new README.md file." + fi + continue-on-error: true + - id: run-terraform-docs + if: steps.validate-readme.outcome == 'success' + uses: terraform-docs/gh-actions@aeae0038ed47a547e0c0fca5c059d3335f48fb25 + with: + working-dir: ${{ inputs.readme-file-path }} + output-file: README.md + output-method: inject + git-push: "true" + + - id: tf-docs-status + if: ( steps.validate-readme.outcome == 'failure' || steps.validate-readme.outcome == 'cancelled' ) + shell: bash + run: exit 1 \ No newline at end of file diff --git a/terraform-docs/helpers.sh b/terraform-docs/helpers.sh new file mode 100755 index 0000000..f8a0e47 --- /dev/null +++ b/terraform-docs/helpers.sh @@ -0,0 +1,40 @@ +#!/bin/env bash + +# Helper consts +_action_name="$(basename "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)")" + +# Helper functions +function _log { echo "${1}${_action_name}: ${2}"; } +function log-info { _log "" "${*}"; } +function log-debug { _log "DEBUG: " "${*}"; } +function log-warn { _log "WARN: " "${*}"; } +function log-error { _log "ERROR: " "${*}"; } +function start-group { echo "::group::${_action_name}: ${*}"; } +function end-group { echo "::endgroup::"; } +function log-multiline { + start-group "${1}" + echo "${2}" + end-group +} +function mask-value { echo "::add-mask::${*}"; } +function set-output { echo "${1}=${2}" >>$GITHUB_OUTPUT; } +function set-multiline-output { + local outputName outputValue delimiter + outputName="${1}" + outputValue="${2}" + delimiter=$(echo $RANDOM | md5sum | head -c 20) + echo "${outputName}<<\"${delimiter}\"" >>$GITHUB_OUTPUT + echo "${outputValue}" >>$GITHUB_OUTPUT + echo "\"${delimiter}\"" >>$GITHUB_OUTPUT +} +function ws-path { + local inPath + inPath="${1}" + realpath --relative-to="${GITHUB_WORKSPACE}" "${inPath}" +} + +log-info "'$(basename ${BASH_SOURCE[0]})' loaded." + +if [ -f "${GITHUB_ACTION_PATH}/helpers_additional.sh" ]; then + source "${GITHUB_ACTION_PATH}/helpers_additional.sh" +fi