|
| 1 | +name: "Setup OpenTofu" |
| 2 | +description: >- |
| 3 | + Composite action to setup OpenTofu such that it can be used on a runner and logging can be sent to |
| 4 | + CloudWatch |
| 5 | +inputs: |
| 6 | + service-path: |
| 7 | + description: "The path to the Terraservice relative to the root of the repository" |
| 8 | + required: true |
| 9 | + cw-log-group: |
| 10 | + description: >- |
| 11 | + Name of CloudWatch Log Group to submit OpenTofu logs to; will be created if necessary |
| 12 | + required: true |
| 13 | + cw-log-stream: |
| 14 | + description: >- |
| 15 | + Name of CloudWatch Log Stream to submit OpenTofu logs to; will be created if necessary |
| 16 | + required: true |
| 17 | + tofu-vars-json: |
| 18 | + description: "JSON object map of variables to their values" |
| 19 | + required: false |
| 20 | + default: "{}" |
| 21 | +runs: |
| 22 | + using: "composite" |
| 23 | + steps: |
| 24 | + # This step is necessary as it seems that some objects (like "github" or "inputs") are |
| 25 | + # unavailable when the top-level "env" is evaluated for Composite Actions |
| 26 | + - name: Setup environment |
| 27 | + run: | |
| 28 | + echo "STDOUT_TO_CWLOGS_SCRIPT=${{ github.workspace }}/.github/scripts/stdout-to-cwlogs.sh" \ |
| 29 | + >> $GITHUB_ENV |
| 30 | + # Necessary for the "stdout-to-cwlogs.sh" script |
| 31 | + echo "CLOUDWATCH_LOG_GROUP=${{ inputs.cw-log-group }}" >> $GITHUB_ENV |
| 32 | + echo "CLOUDWATCH_LOG_STREAM=${{ inputs.cw-log-stream }}" >> $GITHUB_ENV |
| 33 | + shell: bash |
| 34 | + |
| 35 | + - name: Validate inputs |
| 36 | + run: | |
| 37 | + if [[ ! -d "${{ github.workspace }}/${{ inputs.service-path }}" ]]; then |
| 38 | + echo "Directory '${{ inputs.service-path }}' does not exist; has the BFD repo been" \ |
| 39 | + "checked-out?" |
| 40 | + exit 1 |
| 41 | + fi |
| 42 | + shell: bash |
| 43 | + |
| 44 | + - name: Create Log Group if needed |
| 45 | + run: | |
| 46 | + # Attempt to create the Log Group, swallowing any error code that is returned and also |
| 47 | + # capture the stderr output so that it can be checked |
| 48 | + create_log_group_stderr="$( |
| 49 | + aws logs create-log-group \ |
| 50 | + --log-group-name "${{ inputs.cw-log-group }}" 2>&1 >/dev/null || true |
| 51 | + )" |
| 52 | +
|
| 53 | + # If there was an error message logged by create-log-group and that error was not |
| 54 | + # indicating that the Log Group already exists (which is fine), then log that there was an |
| 55 | + # unrecoverable error and exit |
| 56 | + if [[ |
| 57 | + -n $create_log_group_stderr && |
| 58 | + $create_log_group_stderr != *"ResourceAlreadyExistsException"* ]] \ |
| 59 | + ; then |
| 60 | + echo "Unrecoverable error occurred when trying to create Log Group" \ |
| 61 | + "'${{inputs.cw-log-stream }}' in Log Group '${{ inputs.cw-log-group }}'" |
| 62 | + echo "$create_log_group_stderr" |
| 63 | + exit 1 |
| 64 | + fi |
| 65 | + shell: bash |
| 66 | + |
| 67 | + - name: Create Log Stream if needed |
| 68 | + run: | |
| 69 | + create_log_stream_stderr="$( |
| 70 | + aws logs create-log-stream --log-group-name "${{ inputs.cw-log-group }}" \ |
| 71 | + --log-stream-name "${{ inputs.cw-log-stream }}" 2>&1 >/dev/null || true |
| 72 | + )" |
| 73 | +
|
| 74 | + if [[ |
| 75 | + -n $create_log_stream_stderr && |
| 76 | + $create_log_stream_stderr != *"ResourceAlreadyExistsException"* ]] \ |
| 77 | + ; then |
| 78 | + echo "Unrecoverable error occurred when trying to create Log Stream" \ |
| 79 | + "'${{inputs.cw-log-stream }}' in Log Group '${{ inputs.cw-log-group }}'" |
| 80 | + echo "$create_log_stream_stderr" |
| 81 | + exit 1 |
| 82 | + fi |
| 83 | +
|
| 84 | + echo "'${{inputs.cw-log-stream }}' in Log Group '${{ inputs.cw-log-group }}'" \ |
| 85 | + "created or exists already" |
| 86 | + echo "Tail the Log Stream to view OpenTofu output in realtime:" |
| 87 | + echo "aws logs tail --since 1h --follow '${{ inputs.cw-log-group }}'" |
| 88 | + shell: bash |
| 89 | + |
| 90 | + - name: Check if tofu is installed |
| 91 | + id: check-tofu-installed |
| 92 | + run: | |
| 93 | + is_tofu_installed="$( |
| 94 | + if [[ -x "$(command -v tofu)" ]]; then |
| 95 | + echo "true" |
| 96 | + else |
| 97 | + echo "false" |
| 98 | + fi |
| 99 | + )" |
| 100 | + echo "is-tofu-installed=$is_tofu_installed" >> $GITHUB_OUTPUT |
| 101 | + shell: bash |
| 102 | + |
| 103 | + # Maps a given JSON object string of variable names to values, i.e.: |
| 104 | + # { |
| 105 | + # "var1": "val1", |
| 106 | + # "var2": 123, |
| 107 | + # "var3": true |
| 108 | + # } |
| 109 | + # into a space-delimited argument list that the OpenTofu CLI understands: |
| 110 | + # -var=var1=val1 -var=var2=123 -var=var3=true |
| 111 | + - name: Generate OpenTofu vars args |
| 112 | + id: gen-tf-vars-args |
| 113 | + run: | |
| 114 | + tf_vars_args="$( |
| 115 | + echo "${{ inputs.tofu-vars-json }}" | jq -r 'to_entries | |
| 116 | + map(select(.value != null and .value != "")) | |
| 117 | + map("\"-var=" + .key + "=" + (.value | tostring)+ "\"") | |
| 118 | + join(" ")' |
| 119 | + )" |
| 120 | + echo "tf-vars-args=$tf_vars_args" >> $GITHUB_OUTPUT |
| 121 | + shell: bash |
| 122 | + |
| 123 | + - name: Get OpenTofu Version |
| 124 | + if: steps.check-tfvm-installed.outputs.is-tofu-installed == 'false' |
| 125 | + id: get-opentofu-version |
| 126 | + run: | |
| 127 | + cd "${{ github.workspace }}/${{ inputs.service-path }}" |
| 128 | +
|
| 129 | + found_file="" |
| 130 | + current_dir="$PWD" |
| 131 | +
|
| 132 | + # Walk up the directory tree from current working directory |
| 133 | + while [[ "$current_dir" != "/" && -z "$found_file" ]]; do |
| 134 | + if [[ -f "$current_dir/.opentofu-version" ]]; then |
| 135 | + tofu_version="$(head -n 1 "$current_dir/.opentofu-version")" |
| 136 | + found_file="$current_dir/.opentofu-version" |
| 137 | + fi |
| 138 | +
|
| 139 | + # Move to parent directory |
| 140 | + current_dir="$(dirname "$current_dir")" |
| 141 | + done |
| 142 | +
|
| 143 | + if [[ -n "$found_file" ]]; then |
| 144 | + echo "Found .opentofu-version file at $found_file specifying version: $tofu_version" |
| 145 | + else |
| 146 | + echo ".opentofu-version file not found." |
| 147 | + exit 1 |
| 148 | + fi |
| 149 | +
|
| 150 | + echo "tofu-version=$tofu_version" >> $GITHUB_OUTPUT |
| 151 | + shell: bash |
| 152 | + |
| 153 | + - name: Setup OpenTofu |
| 154 | + if: steps.check-tfvm-installed.outputs.is-tofu-installed == 'false' |
| 155 | + uses: opentofu/setup-opentofu@592200bd4b9bbf4772ace78f887668b1aee8f716 # v1.0.5 |
| 156 | + with: |
| 157 | + tofu_version: ${{ steps.get-opentofu-version.outputs.tofu-version }} |
0 commit comments