DEV Community

Cover image for GitHub Actions - Automated Terraform-docs
Cole Heard
Cole Heard

Posted on

GitHub Actions - Automated Terraform-docs

Earlier this year I wrote about the challenges I faced creating a Terraform module. I mentioned then that I was leveraging terraform-docs and GitHub Actions to automate documentation, but a full workflow walkthrough was out of that post's scope.

This post, however, is entirely focused on automated documentation.

If you're looking for an easy way to save time, enforce documentation formatting standards, or ensure documentation is kept up-to-date - my autodoc workflow is a great place to start.



The Workflow

The workflow starts by defining a name, a start condition, and a host that will execute the job.

name: "Autodoc Workflow - Terraform-docs"

on:
  pull_request:

jobs:
  tfdocs:
    runs-on: ubuntu-latest
Enter fullscreen mode Exit fullscreen mode

On a pull request, GitHub Actions will provision a Ubuntu VM with the latest OS version considered "stable" by GitHub.

Note: The -latest runner images are the latest stable images that GitHub provides, and might not be the most recent version of the operating system available from the operating system vendor.

Repo clone

Now that the job has been defined, the first step will clone the repository down to the runner. More specifically, it will pull the PR head from Actions context.

    steps:
    - name: Pull request checkout
      uses: actions/checkout@v3
      id: checkout
      with:
        ref: ${{ github.event.pull_request.head.ref }}
Enter fullscreen mode Exit fullscreen mode

With a local copy of the code now available, the runner can update the documentation.


Generating documentation

This step uses the terraform-docs action to update the README.md.

    - name: README.md generation
      uses: terraform-docs/gh-actions@main
      id: tfdocs
      with:
        config-file: terraform-docs.yaml
        working-dir: .
        output-file: README.md
        output-method: inject
        git-push: "true"
Enter fullscreen mode Exit fullscreen mode

If you'd prefer to install the CLI tool on the runner and execute the commands directly from the shell, other installation options exist.

Action arguments

The terraform-docs action accepts many arguments, but the five below are used by this workflow.

  • config-file accepts the terraform-docs config file.
  • working-dir specifies the location of the terraform files.
  • output-file defines the name of the generated/updated doc.
  • output-method accepts print, replace, or inject. If other content (e.g. content not generated by terraform-docs) exists within the README.md file, you'll want to use inject. Inject updates the existing file and places the newly created documentation between the hardcoded delimiters <!-- BEGIN_TF_DOCS --> and <!-- END_TF_DOCS -->.
  • git-push is set to "true" and adds the newly updated document to the pull request.

Markdown formatting

GitHub understands markdown formatting in readme files, posts, and comments. The terraform-docs.yaml file specifies markdown output to take advantage of this.

formatter: "markdown table"
Enter fullscreen mode Exit fullscreen mode

You can find the full example terraform-docs.yaml file here.

Resulting output

This is what the README.md file looks like after the pull request is merged:
Readme file


Premerge Review

Now that the README.md has been updated, approvers will want to review the changes prior to merging branches.

The next two steps will post updated content to pull request review thread for the approver's convenience.

Echoing contents

The output step echoes the file content into a standard GitHub environmental variable, github_env.

    - name: Output README.md
      id: output
      run: |
        echo 'readme<<EOF' >> $GITHUB_ENV
        echo "$(<README.md)" >> $GITHUB_ENV
        echo 'EOF' >> $GITHUB_ENV
Enter fullscreen mode Exit fullscreen mode

Escape characters

Streaming output of the file into a variable will strip the content of "escape characters", including newline. To preserve these special characters, $(<README.md) is wrapped in double quotes.

echo "$(<README.md)"
Enter fullscreen mode Exit fullscreen mode

Multiline strings

Action's requirements surrounding environmental variables restrict the use of multiline strings. "EOF" (end of file) is used as the delimiter to circumvent this restriction.

echo 'readme<<EOF' >> $GITHUB_ENV
echo "$(<README.md)" >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV
Enter fullscreen mode Exit fullscreen mode

The updated markdown content can now be used in the next step.

Pull request comment

The last step in the workflow creates a comment on the pull request thread in GitHub with the script action.

A fine-grained token grants access to the repository. It is stored as the secret GH_TOKEN.

    - name: Pull request comment
      id: comment
      uses: actions/github-script@v6
      with:
        github-token: ${{ secrets.GH_TOKEN }}
        script: |
          const output = `Terraform-docs has updated the README.md. 

          ${process.env.readme}`
          github.rest.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: output
          })
Enter fullscreen mode Exit fullscreen mode

The markdown stored in the previous step is referenced with ${process.env.readme}.

After the job is completed, this is what the comment looks like:

Pull request comment

Wrapping up

The job is complete and the documentation has been updated! If you'd like to test this workflow yourself, fork and modify my example module - Configure the repository permissions, modify a new branch, and kick off a pull request to see it in action.

If you're interested in learning more about terraform-docs, checkout their user guide or drop by their slack.

Thanks for taking the time read this post!

Ralph Wiggum - Goodbye

Top comments (0)