Compare commits

...

29 commits
v1.0.1 ... main

Author SHA1 Message Date
Diógenes Fernandes
e95ccdd206
Streaming when using tofu_wrapper (#75)
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: Diogenes Fernandes <diofeher@gmail.com>
2025-12-17 12:29:27 -03:00
Diogenes Fernandes
04ba7507e2 update dist
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: Diogenes Fernandes <diofeher@gmail.com>
2025-12-15 19:32:15 -03:00
dependabot[bot]
720194ca9d chore(deps): Bump @actions/core from 1.11.1 to 2.0.1
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.11.1 to 2.0.1.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/@actions/artifact@2.0.1/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-version: 2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 19:32:15 -03:00
Diogenes Fernandes
4738a2ed5e update dist
Signed-off-by: Diogenes Fernandes <diofeher@gmail.com>
2025-12-15 19:25:32 -03:00
dependabot[bot]
bbaf94fb8f chore(deps): Bump @actions/exec from 1.1.1 to 2.0.0
Bumps [@actions/exec](https://github.com/actions/toolkit/tree/HEAD/packages/exec) from 1.1.1 to 2.0.0.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/exec/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/exec)

---
updated-dependencies:
- dependency-name: "@actions/exec"
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 19:25:32 -03:00
Diogenes Fernandes
dc6f440014 Upgrading dist file
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: Diogenes Fernandes <diofeher@gmail.com>
2025-11-20 18:01:47 -03:00
dependabot[bot]
8ff58c1228 chore(deps): Bump @actions/io from 1.1.3 to 2.0.0
Bumps [@actions/io](https://github.com/actions/toolkit/tree/HEAD/packages/io) from 1.1.3 to 2.0.0.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/io/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/io)

---
updated-dependencies:
- dependency-name: "@actions/io"
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-20 18:01:47 -03:00
dependabot[bot]
339b7b2a1b
chore(deps): Bump semver from 7.7.2 to 7.7.3 (#71)
Some checks failed
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Diogenes Fernandes <diofeher@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Diogenes Fernandes <diofeher@gmail.com>
2025-10-14 09:12:51 -03:00
Devin
5e2b22fba4
fix: #45 Add HTTP proxy support (#65)
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: Devin <hoopysoup@users.noreply.github.com>
2025-10-08 11:02:03 -03:00
dependabot[bot]
dd259403c5
chore(deps-dev): Bump jest from 30.1.3 to 30.2.0 (#68)
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-01 04:50:45 -03:00
Diógenes Fernandes
5a7ce099f4
Update CODEOWNERS to assign Dependabot issues (#69)
Signed-off-by: Diógenes Fernandes <diofeher@gmail.com>
2025-10-01 04:28:33 -03:00
dependabot[bot]
58cf7f7458
chore(deps-dev): Bump jest from 30.0.5 to 30.1.3 (#63)
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-24 08:22:34 -03:00
dependabot[bot]
1631e5f6a3
chore(deps-dev): Bump @vercel/ncc from 0.38.3 to 0.38.4 (#66)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-24 08:22:01 -03:00
Diógenes Fernandes
82a7ffce68
Update CODEOWNERS (#67)
Some checks are pending
Continuous Integration / Check dist/ directory (push) Waiting to run
Continuous Integration / Test (push) Waiting to run
Setup OpenTofu / OpenTofu Version Files (push) Waiting to run
Setup OpenTofu / OpenTofu Versions (push) Waiting to run
Setup OpenTofu / OpenTofu Arguments (push) Waiting to run
Setup OpenTofu / OpenTofu Run Local (push) Waiting to run
Setup OpenTofu / OpenTofu Cloud Credentials (push) Waiting to run
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Waiting to run
Setup OpenTofu / OpenTofu No Credentials (push) Waiting to run
Signed-off-by: Diógenes Fernandes <diofeher@gmail.com>
2025-09-23 15:02:41 -03:00
dependabot[bot]
9cc1438d52
chore(deps-dev): Bump jest from 29.7.0 to 30.0.5 (#62)
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 08:13:39 -03:00
dependabot[bot]
d23989bcfc
chore(deps): Bump @actions/tool-cache from 2.0.1 to 2.0.2 (#49)
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 15:16:36 -03:00
dependabot[bot]
868f16c8cb
chore(deps-dev): Bump husky from 9.0.11 to 9.1.7 (#53)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 15:11:09 -03:00
dependabot[bot]
9fc82761c6
chore(deps): Bump semver from 7.5.4 to 7.7.2 (#55)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 15:10:53 -03:00
dependabot[bot]
b16e63e2c6
chore(deps): Bump @actions/core from 1.10.1 to 1.11.1 (#52)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 15:06:56 -03:00
dependabot[bot]
0f0911fca8
chore(deps-dev): Bump @vercel/ncc from 0.38.1 to 0.38.3 (#51)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 15:06:14 -03:00
Brendon Smith
000eeb8522
Add OpenTofu version file support (#59)
Some checks failed
Continuous Integration / Check dist/ directory (push) Has been cancelled
Continuous Integration / Test (push) Has been cancelled
Setup OpenTofu / OpenTofu Version Files (push) Has been cancelled
Setup OpenTofu / OpenTofu Versions (push) Has been cancelled
Setup OpenTofu / OpenTofu Arguments (push) Has been cancelled
Setup OpenTofu / OpenTofu Run Local (push) Has been cancelled
Setup OpenTofu / OpenTofu Cloud Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu Enterprise Credentials (push) Has been cancelled
Setup OpenTofu / OpenTofu No Credentials (push) Has been cancelled
Signed-off-by: Brendon Smith <bws@bws.bio>
2025-08-04 09:32:54 -03:00
AbstractionFactory
4a98c1282d
Readme cleanup (#48)
* Readme cleanup

Signed-off-by: AbstractionFactory <179820029+abstractionfactory@users.noreply.github.com>

* Update README.md

Co-authored-by: Oleksandr Levchenkov <ollevche@gmail.com>
Signed-off-by: AbstractionFactory <179820029+abstractionfactory@users.noreply.github.com>

---------

Signed-off-by: AbstractionFactory <179820029+abstractionfactory@users.noreply.github.com>
Co-authored-by: Oleksandr Levchenkov <ollevche@gmail.com>
2025-02-11 18:20:29 +01:00
AbstractionFactory
592200bd4b
Fixes #43: OpenTofu 1.6 can no longer be downloaded (#44)
* Fixes #43: OpenTofu 1.6 can no longer be downloaded

Signed-off-by: AbstractionFactory <179820029+abstractionfactory@users.noreply.github.com>

* More sane self-test

Signed-off-by: AbstractionFactory <179820029+abstractionfactory@users.noreply.github.com>

---------

Signed-off-by: AbstractionFactory <179820029+abstractionfactory@users.noreply.github.com>
2024-12-10 15:04:33 +01:00
Vladimir Masarik
12f4debbf6
Fix tofu output printing debug information (#31)
Signed-off-by: Vladimir Masarik <masarik.vladimir7@gmail.com>
2024-04-25 14:19:49 +02:00
Kuba Martin
ae80d4ecaa
Fix latest fetching prerelease versions. (#29)
* Fix fetching latest version to not fetch prerelease.

Signed-off-by: Kuba Martin <kubam@spacelift.io>

* Add tests.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

---------

Signed-off-by: Kuba Martin <kubam@spacelift.io>
Signed-off-by: Jakub Martin <kubam@spacelift.io>
2024-03-17 16:01:44 +01:00
dependabot[bot]
d00c6817f1
chore(deps-dev): Bump husky from 8.0.3 to 9.0.11 (#27)
Bumps [husky](https://github.com/typicode/husky) from 8.0.3 to 9.0.11.
- [Release notes](https://github.com/typicode/husky/releases)
- [Commits](https://github.com/typicode/husky/compare/v8.0.3...v9.0.11)

---
updated-dependencies:
- dependency-name: husky
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-21 12:22:29 +02:00
Janos
da3271e0a2
Adding Forgejo support (#23)
Signed-off-by: Janos Bonic <86970079+janosdebugs@users.noreply.github.com>
Co-authored-by: Bence Santha <bence@santha.eu>
2024-01-30 19:49:40 +01:00
RoseSecurity
24b9f144af
Update GitHub Action Branding to Reflect OpenTofu Colors (#20)
Signed-off-by: RoseSecurity <michaeljrosenfeld22@gmail.com>
2024-01-19 18:31:54 +01:00
Rishav Dhar
05c2a037e9
add shell bash to defaults run (#17)
Signed-off-by: Rishav Dhar <19497993+rdhar@users.noreply.github.com>
2023-10-30 18:18:41 +00:00
18 changed files with 57056 additions and 6079 deletions

View file

@ -1,19 +1,19 @@
name: 'Continuous Integration' name: "Continuous Integration"
on: on:
push: push:
branches: branches:
- main - main
pull_request: pull_request:
jobs: jobs:
check-dist: check-dist:
name: Check dist/ directory name: Check dist/ directory
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@967035ce963867fb956a309c9b67512314bc7c1f uses: actions/reusable-workflows/.github/workflows/check-dist.yml@2826fb8353263a138210fc017301ce5767a9c0d4
with: with:
node-version: "20.x" node-version: "20.19.1"
test: test:
name: Test name: Test
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@967035ce963867fb956a309c9b67512314bc7c1f uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@2826fb8353263a138210fc017301ce5767a9c0d4
with: with:
node-version: "20.x" node-version: "20.19.1"

View file

@ -0,0 +1 @@
latest

View file

@ -14,13 +14,32 @@ env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs: jobs:
tofu-version-files:
name: 'OpenTofu Version Files'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
tofu-version-files: ['./.github/workflows/data/local/.opentofu-version']
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup OpenTofu - ${{ matrix['tofu-version-files'] }}
uses: ./
with:
tofu_version_file: ${{ matrix['tofu-version-files'] }}
tofu_wrapper: false
- name: Validate that OpenTofu was installed
run: tofu version | grep 'OpenTofu v'
tofu-versions: tofu-versions:
name: 'OpenTofu Versions' name: 'OpenTofu Versions'
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
tofu-versions: [1.6.0-alpha1, latest] tofu-versions: [1.6.0, latest]
tofu-wrapper: [true, false] tofu-wrapper: [true, false]
steps: steps:
- name: Checkout - name: Checkout
@ -80,6 +99,7 @@ jobs:
tofu-wrapper: [true, false] tofu-wrapper: [true, false]
defaults: defaults:
run: run:
shell: bash
working-directory: ./.github/workflows/data/local working-directory: ./.github/workflows/data/local
steps: steps:
- name: Checkout - name: Checkout

View file

@ -4,4 +4,9 @@
# We currently do not have any specific code owners # We currently do not have any specific code owners
# In the future, we will have a Github team of global code owners of the entire package # In the future, we will have a Github team of global code owners of the entire package
# Later on, we will start splitting up the responsibilities, and packages will be assigned more specific code owners # Later on, we will start splitting up the responsibilities, and packages will be assigned more specific code owners
# * @opentofu-code-owners * @opentofu/maintainers
# The last matching pattern takes the most precedence for CODEOWNERS. CODEOWNERS does not have fine-grained control so we will
# just match whole changes for these specific files, but @diofeher is responsible for taking care of the Dependabot updates
# in this repository.
package*.json @diofeher

View file

@ -1,10 +0,0 @@
# Code of Conduct
We follow the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).
<!-- TODO: Decide who will handle Code of Conduct reports and replace [INSERT EMAIL ADDRESS]
with an email address in the paragraph below. We recommend using a mailing list to handle reports.
If your project isn't prepared to handle reports, remove the project email address and just have
reporters send to conduct@cncf.io.
-->
Please contact contact@opentf.org in order to report violations of the Code of Conduct.

View file

@ -1,18 +1,12 @@
# setup-opentofu # GitHub Action for setting up OpenTofu
The `opentofu/setup-opentofu` action sets up OpenTofu CLI in your GitHub Actions workflow by: > [!NOTE]
> This is a community-maintained repository. The OpenTofu team does not fix non-critical bugs or add features, but is happy to review community pull requests.
- Downloading the latest version of OpenTofu CLI and adding it to the `PATH`. > [!TIP]
- Configuring the [CLI configuration file](https://opentofu.org/docs/cli/config/config-file/) with a Terraform Cloud/Enterprise hostname and API token. > Having trouble with exit codes or the output format? Try setting the `tofu_wrapper` setting to `false`.
- Installing a wrapper script to wrap subsequent calls of the `tofu` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. (This can be optionally skipped if subsequent steps in the same job do not need to access the results of
OpenTofu commands.)
After you've used the action, subsequent steps in the same job can run arbitrary OpenTofu commands using [the GitHub Actions `run` syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun). This allows most OpenTofu commands to work exactly The `opentofu/setup-opentofu` action sets up OpenTofu CLI in GitHub Actions.
like they do on your local command line.
## Experimental Status
By using the software in this repository (the "Software"), you acknowledge that: (1) the Software is still in development, may change, and has not been released as a commercial product by OpenTofu; (2) the Software is provided on an "as-is" basis, and may include bugs, errors, or other issues; (3) the Software is NOT INTENDED FOR PRODUCTION USE, use of the Software may result in unexpected results, loss of data, or other unexpected results, and OpenTofu disclaims any and all liability resulting from use of the Software.
## Usage ## Usage
@ -31,9 +25,20 @@ A specific version of OpenTofu CLI can be installed:
steps: steps:
- uses: opentofu/setup-opentofu@v1 - uses: opentofu/setup-opentofu@v1
with: with:
tofu_version: 1.6.0-alpha1 tofu_version: 1.6.0
``` ```
You can also specify the version in a file (e.g., `.opentofu-version`):
```yaml
steps:
- uses: opentofu/setup-opentofu@v1
with:
tofu_version_file: .opentofu-version
```
Supported version syntax is the same as for the `tofu_version` input. If both `tofu_version` and `tofu_version_file` are provided, the version number in the file takes precedence.
Credentials for Terraform Cloud ([app.terraform.io](https://app.terraform.io/)) can be configured: Credentials for Terraform Cloud ([app.terraform.io](https://app.terraform.io/)) can be configured:
```yaml ```yaml
@ -254,9 +259,12 @@ The action supports the following inputs:
for available range specifications). Examples are: `<1.6.0-beta`, `~1.6.0-alpha`, `1.6.0-alpha2` (all three installing for available range specifications). Examples are: `<1.6.0-beta`, `~1.6.0-alpha`, `1.6.0-alpha2` (all three installing
the latest available `1.6.0-alpha2` version). Prerelease versions can be specified and a range will stay within the the latest available `1.6.0-alpha2` version). Prerelease versions can be specified and a range will stay within the
given tag such as `beta` or `rc`. If no version is given, it will default to `latest`. given tag such as `beta` or `rc`. If no version is given, it will default to `latest`.
- `tofu_version_file` - (optional) Path to a file containing the OpenTofu version to install. Supported version syntax
is the same as for the `tofu_version` input. Takes precedence over `tofu_version` if both are provided.
- `tofu_wrapper` - (optional) Whether to install a wrapper to wrap subsequent calls of - `tofu_wrapper` - (optional) Whether to install a wrapper to wrap subsequent calls of
the `tofu` binary and expose its STDOUT, STDERR, and exit code as outputs the `tofu` binary and expose its STDOUT, STDERR, and exit code as outputs
named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`. named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`.
- `github_token` - (optional) Override the GitHub token read from the environment variable. Defaults to the value of the `GITHUB_TOKEN` environment variable unless running on Forgejo or Gitea.
## Outputs ## Outputs
@ -271,6 +279,3 @@ to `true`, the following outputs are available for subsequent steps that call th
[Mozilla Public License v2.0](LICENSE) [Mozilla Public License v2.0](LICENSE)
## Code of Conduct
[Code of Conduct](CODE_OF_CONDUCT.md)

View file

@ -13,10 +13,17 @@ inputs:
description: 'The version of OpenTofu CLI to install. If no version is given, it will default to `latest`.' description: 'The version of OpenTofu CLI to install. If no version is given, it will default to `latest`.'
default: 'latest' default: 'latest'
required: false required: false
tofu_version_file:
description: 'Path to a file containing the OpenTofu version to install. Takes precedence over `tofu_version` if both are provided.'
required: false
tofu_wrapper: tofu_wrapper:
description: 'Whether or not to install a wrapper to wrap subsequent calls of the `tofu` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`.' description: 'Whether or not to install a wrapper to wrap subsequent calls of the `tofu` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`.'
default: 'true' default: 'true'
required: false required: false
github_token:
description: 'API token for GitHub to increase the rate limit. Defaults to the GITHUB_TOKEN environment variable unless running on Forgejo/Gitea.'
default: ''
required: false
outputs: outputs:
stdout: stdout:
description: 'The STDOUT stream of the call to the `tofu` binary.' description: 'The STDOUT stream of the call to the `tofu` binary.'
@ -29,8 +36,8 @@ outputs:
value: '126' value: '126'
branding: branding:
icon: 'terminal' icon: 'box'
color: 'purple' color: 'yellow'
runs: runs:
using: 'node20' using: 'node20'
main: 'dist/index.js' main: 'dist/index.js'

31901
dist/index.js vendored

File diff suppressed because one or more lines are too long

27040
dist/index1.js vendored

File diff suppressed because one or more lines are too long

View file

@ -4,16 +4,16 @@
*/ */
class Build { class Build {
constructor (name, url) { constructor (version, name) {
this.name = name; this.name = name;
this.url = url; this.url = 'https://github.com/opentofu/opentofu/releases/download/v' + version + '/' + name;
} }
} }
class Release { class Release {
constructor (releaseMeta) { constructor (releaseMeta) {
this.version = releaseMeta.tag_name.replace('v', ''); this.version = releaseMeta.id.replace('v', '');
this.builds = releaseMeta.assets.map(asset => new Build(asset.name, asset.browser_download_url)); this.builds = releaseMeta.files.map(asset => new Build(this.version, asset));
} }
getBuild (platform, arch) { getBuild (platform, arch) {
@ -27,35 +27,39 @@ class Release {
* *
* @return {Array<Release>} Releases. * @return {Array<Release>} Releases.
*/ */
async function fetchReleases () { async function fetchReleases (githubToken) {
const url = 'https://api.github.com/repos/opentofu/opentofu/releases'; const hc = require('@actions/http-client');
const userAgent = 'opentofu/setup-opentofu';
const http = new hc.HttpClient(userAgent);
const url = 'https://get.opentofu.org/tofu/api.json';
const headers = { const headers = {
Accept: 'application/vnd.github+json', Accept: 'application/json'
'X-GitHub-Api-Version': '2022-11-28'
}; };
if (process.env.GITHUB_TOKEN) { const resp = await http.get(url, headers);
headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
if (resp.message.statusCode !== hc.HttpCodes.OK) {
throw new Error('failed fetching releases (' + resp.message.statusCode + ')');
} }
const resp = await fetch(url, { const body = await resp.readBody();
headers const releasesMeta = JSON.parse(body);
});
if (!resp.ok) { /**
throw new Error('failed fetching releases'); * @type {Array}
} */
const versions = releasesMeta.versions;
const releasesMeta = await resp.json(); return versions.map(releaseMeta => new Release(releaseMeta));
return releasesMeta.map(releaseMeta => new Release(releaseMeta));
} }
const semver = require('semver'); const semver = require('semver');
async function findLatestVersion (versions) { async function findLatestVersion (versions) {
return versions.sort((a, b) => semver.rcompare(a, b))[0]; return versions.filter((v) => semver.prerelease(v) === null).sort((a, b) => semver.rcompare(a, b))[0];
} }
async function findLatestVersionInRange (versions, range) { async function findLatestVersionInRange (versions, range) {
@ -66,10 +70,11 @@ async function findLatestVersionInRange (versions, range) {
* Fetches the release given the version. * Fetches the release given the version.
* *
* @param {string} version: Release version. * @param {string} version: Release version.
* @param {string} githubToken: GitHub token to use for working around rate limits.
* @param {function} fetchReleasesFn: Optional function to fetch releases. * @param {function} fetchReleasesFn: Optional function to fetch releases.
* @return {Release} Release. * @return {Release} Release.
*/ */
async function getRelease (version, fetchReleasesFn = fetchReleases) { async function getRelease (version, githubToken, fetchReleasesFn = fetchReleases) {
const latestVersionLabel = 'latest'; const latestVersionLabel = 'latest';
const versionsRange = semver.validRange(version, { prerelease: true, loose: true }); const versionsRange = semver.validRange(version, { prerelease: true, loose: true });
@ -77,7 +82,7 @@ async function getRelease (version, fetchReleasesFn = fetchReleases) {
throw new Error('Input version cannot be used, see semver: https://semver.org/spec/v2.0.0.html'); throw new Error('Input version cannot be used, see semver: https://semver.org/spec/v2.0.0.html');
} }
const releases = await fetchReleasesFn(); const releases = await fetchReleasesFn(githubToken);
if (releases === null || releases.length === 0) { if (releases === null || releases.length === 0) {
throw new Error('No tofu releases found, please contact OpenTofu'); throw new Error('No tofu releases found, please contact OpenTofu');

View file

@ -48,7 +48,7 @@ async function downloadAndExtractCLI (url) {
if (os.platform().startsWith('win')) { if (os.platform().startsWith('win')) {
core.debug(`OpenTofu CLI Download Path is ${pathToCLIZip}`); core.debug(`OpenTofu CLI Download Path is ${pathToCLIZip}`);
const fixedPathToCLIZip = `${pathToCLIZip}.zip`; const fixedPathToCLIZip = `${pathToCLIZip}.zip`;
io.mv(pathToCLIZip, fixedPathToCLIZip); await io.mv(pathToCLIZip, fixedPathToCLIZip);
core.debug(`Moved download to ${fixedPathToCLIZip}`); core.debug(`Moved download to ${fixedPathToCLIZip}`);
pathToCLI = await tc.extractZip(fixedPathToCLIZip); pathToCLI = await tc.extractZip(fixedPathToCLIZip);
} else { } else {
@ -105,7 +105,7 @@ async function addCredentials (credentialsHostname, credentialsToken, osPlat) {
credentials "${credentialsHostname}" { credentials "${credentialsHostname}" {
token = "${credentialsToken}" token = "${credentialsToken}"
}`.trim(); }`.trim();
// eslint-enable // eslint-enable
// default to OS-specific path // default to OS-specific path
let credsFile = osPlat === 'win32' let credsFile = osPlat === 'win32'
@ -128,17 +128,45 @@ credentials "${credentialsHostname}" {
async function run () { async function run () {
try { try {
// Gather GitHub Actions inputs // Gather GitHub Actions inputs
const version = core.getInput('tofu_version'); let version = core.getInput('tofu_version');
const versionFile = core.getInput('tofu_version_file');
const credentialsHostname = core.getInput('cli_config_credentials_hostname'); const credentialsHostname = core.getInput('cli_config_credentials_hostname');
const credentialsToken = core.getInput('cli_config_credentials_token'); const credentialsToken = core.getInput('cli_config_credentials_token');
const wrapper = core.getInput('tofu_wrapper') === 'true'; const wrapper = core.getInput('tofu_wrapper') === 'true';
let githubToken = core.getInput('github_token');
if (githubToken === '' && !(process.env.FORGEJO_ACTIONS || process.env.GITEA_ACTIONS)) {
// Only default to the environment variable when running in GitHub Actions. Don't do this for other CI systems
// that may set the GITHUB_TOKEN environment variable.
githubToken = process.env.GITHUB_TOKEN;
}
// If tofu_version_file is provided, read the version from the file
if (versionFile) {
try {
core.debug(`Reading OpenTofu version from file: ${versionFile}`);
const fileVersion = await fs.readFile(versionFile, 'utf8');
const trimmedVersion = fileVersion.trim();
if (trimmedVersion) {
version = trimmedVersion;
core.debug(`Using version from file: ${version}`);
} else {
core.warning(
`Version file ${versionFile} is empty, using tofu_version input: ${version}`
);
}
} catch (error) {
core.warning(
`Failed to read version from file ${versionFile}: ${error.message}. Using tofu_version input: ${version}`
);
}
}
// Gather OS details // Gather OS details
const osPlatform = os.platform(); const osPlatform = os.platform();
const osArch = os.arch(); const osArch = os.arch();
core.debug(`Finding releases for OpenTofu version ${version}`); core.debug(`Finding releases for OpenTofu version ${version}`);
const release = await releases.getRelease(version); const release = await releases.getRelease(version, githubToken);
const platform = mapOS(osPlatform); const platform = mapOS(osPlatform);
const arch = mapArch(osArch); const arch = mapArch(osArch);
const build = release.getBuild(platform, arch); const build = release.getBuild(platform, arch);

View file

@ -3,184 +3,133 @@ const pkg = require('../releases');
describe('getRelease', () => { describe('getRelease', () => {
function mockFetchReleases () { function mockFetchReleases () {
const mockReleasesMeta = [{ const mockReleasesMeta = [{
tag_name: 'v1.6.0-alpha2', id: 'v1.7.0-alpha2',
assets: [{ files: [
name: 'tofu_1.6.0-alpha2_386.apk', 'tofu_1.7.0-alpha2_386.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_386.apk' 'tofu_1.7.0-alpha2_386.deb',
}, { 'tofu_1.7.0-alpha2_386.rpm',
name: 'tofu_1.6.0-alpha2_386.deb', 'tofu_1.7.0-alpha2_amd64.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_386.deb' 'tofu_1.7.0-alpha2_amd64.deb',
}, { 'tofu_1.7.0-alpha2_amd64.rpm',
name: 'tofu_1.6.0-alpha2_386.rpm', 'tofu_1.7.0-alpha2_arm.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_386.rpm' 'tofu_1.7.0-alpha2_arm.deb',
}, { 'tofu_1.7.0-alpha2_arm.rpm',
name: 'tofu_1.6.0-alpha2_amd64.apk', 'tofu_1.7.0-alpha2_arm64.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_amd64.apk' 'tofu_1.7.0-alpha2_arm64.deb',
}, { 'tofu_1.7.0-alpha2_arm64.rpm',
name: 'tofu_1.6.0-alpha2_amd64.deb', 'tofu_1.7.0-alpha2_darwin_arm64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_amd64.deb' 'tofu_1.7.0-alpha2_freebsd_386.zip',
}, { 'tofu_1.7.0-alpha2_freebsd_amd64.zip',
name: 'tofu_1.6.0-alpha2_amd64.rpm', 'tofu_1.7.0-alpha2_freebsd_arm.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_amd64.rpm' 'tofu_1.7.0-alpha2_linux_386.zip',
}, { 'tofu_1.7.0-alpha2_linux_amd64.zip',
name: 'tofu_1.6.0-alpha2_arm.apk', 'tofu_1.7.0-alpha2_linux_arm.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_arm.apk' 'tofu_1.7.0-alpha2_linux_arm64.zip',
}, { 'tofu_1.7.0-alpha2_openbsd_386.zip',
name: 'tofu_1.6.0-alpha2_arm.deb', 'tofu_1.7.0-alpha2_openbsd_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_arm.deb' 'tofu_1.7.0-alpha2_SHA256SUMS',
}, { 'tofu_1.7.0-alpha2_SHA256SUMS.pem',
name: 'tofu_1.6.0-alpha2_arm.rpm', 'tofu_1.7.0-alpha2_SHA256SUMS.sig',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_arm.rpm' 'tofu_1.7.0-alpha2_solaris_amd64.zip',
}, { 'tofu_1.7.0-alpha2_windows_386.zip',
name: 'tofu_1.6.0-alpha2_arm64.apk', 'tofu_1.7.0-alpha2_windows_amd64.zip'
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_arm64.apk' ]
}, {
name: 'tofu_1.6.0-alpha2_arm64.deb',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_arm64.deb'
}, {
name: 'tofu_1.6.0-alpha2_arm64.rpm',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_arm64.rpm'
}, {
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_darwin_amd64.zip'
}, {
name: 'tofu_1.6.0-alpha2_darwin_arm64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_darwin_arm64.zip'
}, {
name: 'tofu_1.6.0-alpha2_freebsd_386.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_freebsd_386.zip'
}, {
name: 'tofu_1.6.0-alpha2_freebsd_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_freebsd_amd64.zip'
}, {
name: 'tofu_1.6.0-alpha2_freebsd_arm.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_freebsd_arm.zip'
}, {
name: 'tofu_1.6.0-alpha2_linux_386.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_linux_386.zip'
}, {
name: 'tofu_1.6.0-alpha2_linux_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_linux_amd64.zip'
}, {
name: 'tofu_1.6.0-alpha2_linux_arm.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_linux_arm.zip'
}, {
name: 'tofu_1.6.0-alpha2_linux_arm64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_linux_arm64.zip'
}, {
name: 'tofu_1.6.0-alpha2_openbsd_386.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_openbsd_386.zip'
}, {
name: 'tofu_1.6.0-alpha2_openbsd_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_openbsd_amd64.zip'
}, {
name: 'tofu_1.6.0-alpha2_SHA256SUMS',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_SHA256SUMS'
}, {
name: 'tofu_1.6.0-alpha2_SHA256SUMS.pem',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_SHA256SUMS.pem'
}, {
name: 'tofu_1.6.0-alpha2_SHA256SUMS.sig',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_SHA256SUMS.sig'
}, {
name: 'tofu_1.6.0-alpha2_solaris_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_solaris_amd64.zip'
}, {
name: 'tofu_1.6.0-alpha2_windows_386.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_windows_386.zip'
}, {
name: 'tofu_1.6.0-alpha2_windows_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha2/tofu_1.6.0-alpha2_windows_amd64.zip'
}]
}, { }, {
tag_name: 'v1.6.0-alpha1', id: 'v1.6.0',
assets: [{ files: [
name: 'tofu_1.6.0-alpha1_386.apk', 'tofu_1.6.0_386.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_386.apk' 'tofu_1.6.0_386.deb',
}, { 'tofu_1.6.0_386.rpm',
name: 'tofu_1.6.0-alpha1_386.deb', 'tofu_1.6.0_amd64.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_386.deb' 'tofu_1.6.0_amd64.deb',
}, { 'tofu_1.6.0_amd64.rpm',
name: 'tofu_1.6.0-alpha1_386.rpm', 'tofu_1.6.0_arm.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_386.rpm' 'tofu_1.6.0_arm.deb',
}, { 'tofu_1.6.0_arm.rpm',
name: 'tofu_1.6.0-alpha1_amd64.apk', 'tofu_1.6.0_arm64.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_amd64.apk' 'tofu_1.6.0_arm64.deb',
}, { 'tofu_1.6.0_arm64.rpm',
name: 'tofu_1.6.0-alpha1_amd64.deb', 'tofu_1.6.0_darwin_arm64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_amd64.deb' 'tofu_1.6.0_freebsd_386.zip',
}, { 'tofu_1.6.0_freebsd_amd64.zip',
name: 'tofu_1.6.0-alpha1_amd64.rpm', 'tofu_1.6.0_freebsd_arm.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_amd64.rpm' 'tofu_1.6.0_linux_386.zip',
}, { 'tofu_1.6.0_linux_amd64.zip',
name: 'tofu_1.6.0-alpha1_arm.apk', 'tofu_1.6.0_linux_arm.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_arm.apk' 'tofu_1.6.0_linux_arm64.zip',
}, { 'tofu_1.6.0_openbsd_386.zip',
name: 'tofu_1.6.0-alpha1_arm.deb', 'tofu_1.6.0_openbsd_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_arm.deb' 'tofu_1.6.0_SHA256SUMS',
}, { 'tofu_1.6.0_SHA256SUMS.pem',
name: 'tofu_1.6.0-alpha1_arm.rpm', 'tofu_1.6.0_SHA256SUMS.sig',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_arm.rpm' 'tofu_1.6.0_solaris_amd64.zip',
}, { 'tofu_1.6.0_windows_386.zip',
name: 'tofu_1.6.0-alpha1_arm64.apk', 'tofu_1.6.0_windows_amd64.zip']
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_arm64.apk' }, {
}, { id: 'v1.6.0-alpha2',
name: 'tofu_1.6.0-alpha1_arm64.deb', files: [
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_arm64.deb' 'tofu_1.6.0-alpha2_386.apk',
}, { 'tofu_1.6.0-alpha2_386.deb',
name: 'tofu_1.6.0-alpha1_arm64.rpm', 'tofu_1.6.0-alpha2_386.rpm',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_arm64.rpm' 'tofu_1.6.0-alpha2_amd64.apk',
}, { 'tofu_1.6.0-alpha2_amd64.deb',
name: 'tofu_1.6.0-alpha1_darwin_amd64.zip', 'tofu_1.6.0-alpha2_amd64.rpm',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_darwin_amd64.zip' 'tofu_1.6.0-alpha2_arm.apk',
}, { 'tofu_1.6.0-alpha2_arm.deb',
name: 'tofu_1.6.0-alpha1_darwin_arm64.zip', 'tofu_1.6.0-alpha2_arm.rpm',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_darwin_arm64.zip' 'tofu_1.6.0-alpha2_arm64.apk',
}, { 'tofu_1.6.0-alpha2_arm64.deb',
name: 'tofu_1.6.0-alpha1_freebsd_386.zip', 'tofu_1.6.0-alpha2_arm64.rpm',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_freebsd_386.zip' 'tofu_1.6.0-alpha2_darwin_arm64.zip',
}, { 'tofu_1.6.0-alpha2_freebsd_386.zip',
name: 'tofu_1.6.0-alpha1_freebsd_amd64.zip', 'tofu_1.6.0-alpha2_freebsd_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_freebsd_amd64.zip' 'tofu_1.6.0-alpha2_freebsd_arm.zip',
}, { 'tofu_1.6.0-alpha2_linux_386.zip',
name: 'tofu_1.6.0-alpha1_freebsd_arm.zip', 'tofu_1.6.0-alpha2_linux_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_freebsd_arm.zip' 'tofu_1.6.0-alpha2_linux_arm.zip',
}, { 'tofu_1.6.0-alpha2_linux_arm64.zip',
name: 'tofu_1.6.0-alpha1_linux_386.zip', 'tofu_1.6.0-alpha2_openbsd_386.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_linux_386.zip' 'tofu_1.6.0-alpha2_openbsd_amd64.zip',
}, { 'tofu_1.6.0-alpha2_SHA256SUMS',
name: 'tofu_1.6.0-alpha1_linux_amd64.zip', 'tofu_1.6.0-alpha2_SHA256SUMS.pem',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_linux_amd64.zip' 'tofu_1.6.0-alpha2_SHA256SUMS.sig',
}, { 'tofu_1.6.0-alpha2_solaris_amd64.zip',
name: 'tofu_1.6.0-alpha1_linux_arm.zip', 'tofu_1.6.0-alpha2_windows_386.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_linux_arm.zip' 'tofu_1.6.0-alpha2_windows_amd64.zip'
}, { ]
name: 'tofu_1.6.0-alpha1_linux_arm64.zip', }, {
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_linux_arm64.zip' id: 'v1.6.0-alpha1',
}, { files: [
name: 'tofu_1.6.0-alpha1_openbsd_386.zip', 'tofu_1.6.0-alpha1_386.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_openbsd_386.zip' 'tofu_1.6.0-alpha1_386.deb',
}, { 'tofu_1.6.0-alpha1_386.rpm',
name: 'tofu_1.6.0-alpha1_openbsd_amd64.zip', 'tofu_1.6.0-alpha1_amd64.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_openbsd_amd64.zip' 'tofu_1.6.0-alpha1_amd64.deb',
}, { 'tofu_1.6.0-alpha1_amd64.rpm',
name: 'tofu_1.6.0-alpha1_SHA256SUMS', 'tofu_1.6.0-alpha1_arm.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_SHA256SUMS' 'tofu_1.6.0-alpha1_arm.deb',
}, { 'tofu_1.6.0-alpha1_arm.rpm',
name: 'tofu_1.6.0-alpha1_SHA256SUMS.pem', 'tofu_1.6.0-alpha1_arm64.apk',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_SHA256SUMS.pem' 'tofu_1.6.0-alpha1_arm64.deb',
}, { 'tofu_1.6.0-alpha1_arm64.rpm',
name: 'tofu_1.6.0-alpha1_SHA256SUMS.sig', 'tofu_1.6.0-alpha1_darwin_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_SHA256SUMS.sig' 'tofu_1.6.0-alpha1_darwin_arm64.zip',
}, { 'tofu_1.6.0-alpha1_freebsd_386.zip',
name: 'tofu_1.6.0-alpha1_solaris_amd64.zip', 'tofu_1.6.0-alpha1_freebsd_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_solaris_amd64.zip' 'tofu_1.6.0-alpha1_freebsd_arm.zip',
}, { 'tofu_1.6.0-alpha1_linux_386.zip',
name: 'tofu_1.6.0-alpha1_windows_386.zip', 'tofu_1.6.0-alpha1_linux_amd64.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_windows_386.zip' 'tofu_1.6.0-alpha1_linux_arm.zip',
}, { 'tofu_1.6.0-alpha1_linux_arm64.zip',
name: 'tofu_1.6.0-alpha1_windows_amd64.zip', 'tofu_1.6.0-alpha1_openbsd_386.zip',
browser_download_url: 'https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_windows_amd64.zip' 'tofu_1.6.0-alpha1_openbsd_amd64.zip',
}] 'tofu_1.6.0-alpha1_SHA256SUMS',
'tofu_1.6.0-alpha1_SHA256SUMS.pem',
'tofu_1.6.0-alpha1_SHA256SUMS.sig',
'tofu_1.6.0-alpha1_solaris_amd64.zip',
'tofu_1.6.0-alpha1_windows_386.zip',
'tofu_1.6.0-alpha1_windows_amd64.zip'
]
}]; }];
return mockReleasesMeta.map(el => new pkg.Release(el)); return mockReleasesMeta.map(el => new pkg.Release(el));
@ -188,16 +137,19 @@ describe('getRelease', () => {
it.each( it.each(
[ [
['latest', '1.6.0-alpha2'], ['latest', '1.6.0'],
['<1.6.0-beta', '1.6.0-alpha2'], ['<1.6.0-beta', '1.6.0-alpha2'],
['>1.6.0-alpha1', '1.6.0-alpha2'], ['>1.6.0-alpha1', '1.6.0'],
['>1.6.0-alpha1 <1.6.0', '1.6.0-alpha2'], ['>1.6.0-alpha1 <1.6.0', '1.6.0-alpha2'],
['~1.6.0-alpha', '1.6.0-alpha2'], ['~1.6.0-alpha', '1.6.0'],
['<=1.6.0-alpha1', '1.6.0-alpha1'] ['<=1.6.0-alpha1', '1.6.0-alpha1'],
['>1.5.0', '1.6.0'],
['>1.5.0', '1.6.0'],
['>1.7.0-alpha', '1.7.0-alpha2']
] ]
)('happy path: getRelease(\'%s\') -> \'%s\'', async (input, wantVersion) => { )('happy path: getRelease(\'%s\') -> \'%s\'', async (input, wantVersion) => {
const want = mockFetchReleases().find(el => el.version === wantVersion); const want = mockFetchReleases().find(el => el.version === wantVersion);
const gotRelease = await pkg.getRelease(input, mockFetchReleases); const gotRelease = await pkg.getRelease(input, '', mockFetchReleases);
expect(gotRelease).toEqual(want); expect(gotRelease).toEqual(want);
}); });
@ -205,12 +157,16 @@ describe('getRelease', () => {
[ [
['foo', 'Input version cannot be used, see semver: https://semver.org/spec/v2.0.0.html', mockFetchReleases], ['foo', 'Input version cannot be used, see semver: https://semver.org/spec/v2.0.0.html', mockFetchReleases],
['2.0', 'No matching version found', mockFetchReleases], ['2.0', 'No matching version found', mockFetchReleases],
['latest', 'No tofu releases found, please contact OpenTofu', async () => { return null; }], ['latest', 'No tofu releases found, please contact OpenTofu', async () => {
['latest', 'No tofu releases found, please contact OpenTofu', async () => { return []; }] return null;
}],
['latest', 'No tofu releases found, please contact OpenTofu', async () => {
return [];
}]
] ]
)('unhappy path: getRelease(\'%s\') -> throw Error(\'%s\')', async (input, wantErrorMessage, mockFetchReleasesFn) => { )('unhappy path: getRelease(\'%s\') -> throw Error(\'%s\')', async (input, wantErrorMessage, mockFetchReleasesFn) => {
try { try {
await pkg.getRelease(input, mockFetchReleasesFn); await pkg.getRelease(input, '', mockFetchReleasesFn);
expect(true).toBe(false); expect(true).toBe(false);
} catch (e) { } catch (e) {
expect(e.message).toBe(wantErrorMessage); expect(e.message).toBe(wantErrorMessage);

176
lib/test/setup-tofu.test.js Normal file
View file

@ -0,0 +1,176 @@
// Node.js core
const fs = require('fs').promises;
const os = require('os');
const path = require('path');
// External
const core = require('@actions/core');
// First party
const releases = require('../releases');
const setup = require('../setup-tofu');
// Mock dependencies
jest.mock('@actions/core');
jest.mock('@actions/io', () => ({
mv: jest.fn(),
cp: jest.fn(),
mkdirP: jest.fn()
}));
jest.mock('@actions/tool-cache', () => ({
downloadTool: jest.fn(),
extractZip: jest.fn()
}));
// Mock releases.js so setup-tofu.js can be tested in isolation
jest.mock('../releases');
// Set up global test fixtures
const fallbackVersion = 'latest';
let tempDir;
let tempDirPath;
let version = '1.10.5';
let versionFile;
let versionFileName = '.opentofu-version';
describe('setup-tofu', () => {
beforeAll(async () => {
// Mock dependencies
const tc = require('@actions/tool-cache');
tc.downloadTool.mockResolvedValue('/mock/download/path');
tc.extractZip.mockResolvedValue('/mock/extract/path');
const io = require('@actions/io');
io.mv.mockResolvedValue();
io.cp.mockResolvedValue();
io.mkdirP.mockResolvedValue();
const mockRelease = {
getBuild: jest.fn().mockReturnValue({ url: 'mock-url' })
};
releases.getRelease.mockResolvedValue(mockRelease);
// Write version file to temporary directory
tempDirPath = path.join(os.tmpdir(), 'setup-tofu-');
tempDir = await fs.mkdtemp(tempDirPath);
versionFile = path.join(tempDir, versionFileName);
await fs.writeFile(versionFile, `${version}\n`);
// Mock action inputs to return default values
core.getInput.mockImplementation((name) => {
const defaults = {
tofu_version: fallbackVersion,
tofu_version_file: versionFile,
cli_config_credentials_hostname: '',
cli_config_credentials_token: '',
tofu_wrapper: 'true',
github_token: ''
};
return defaults[name] || '';
});
// Mock environment variables
process.env.GITHUB_TOKEN = 'mock-github-token';
});
beforeEach(() => {
jest.clearAllMocks();
});
afterAll(async () => {
delete process.env.GITHUB_TOKEN;
});
describe('tofu_version_file functionality', () => {
it('should read version from file when tofu_version_file is provided', async () => {
jest.spyOn(fs, 'readFile');
await setup();
expect(releases.getRelease).toHaveBeenCalledWith(
version, process.env.GITHUB_TOKEN
);
expect(fs.readFile).toHaveBeenCalled();
});
it('should handle empty version file gracefully', async () => {
jest.spyOn(fs, 'readFile');
version = ' ';
versionFileName = '.opentofu-version-empty';
versionFile = path.join(tempDir, versionFileName);
await fs.writeFile(versionFile, `${version}\n`);
core.getInput.mockImplementation((name) => {
if (name === 'tofu_version_file') {
return versionFile;
}
if (name === 'tofu_version') {
return fallbackVersion;
}
return '';
});
await setup();
expect(releases.getRelease).toHaveBeenCalledWith(
fallbackVersion, process.env.GITHUB_TOKEN
);
expect(core.warning).toHaveBeenCalledWith(
expect.stringContaining(`Version file ${versionFile} is empty`)
);
expect(fs.readFile).toHaveBeenCalled();
});
it('should handle file read errors gracefully', async () => {
jest.spyOn(fs, 'readFile');
versionFileName = '.opentofu-version-file-does-not-exist';
versionFile = path.join(tempDir, versionFileName);
core.getInput.mockImplementation((name) => {
if (name === 'tofu_version_file') {
return versionFile;
}
if (name === 'tofu_version') {
return fallbackVersion;
}
return '';
});
await setup();
expect(releases.getRelease).toHaveBeenCalledWith(
fallbackVersion, process.env.GITHUB_TOKEN
);
expect(core.warning).toHaveBeenCalledWith(
expect.stringContaining(`Failed to read version from file ${versionFile}`)
);
expect(fs.readFile).toHaveBeenCalled();
});
it('should not read file when tofu_version_file is not provided', async () => {
jest.spyOn(fs, 'readFile');
core.getInput.mockImplementation((name) => {
if (name === 'tofu_version') {
return fallbackVersion;
}
return '';
});
await setup();
expect(releases.getRelease).toHaveBeenCalledWith(
fallbackVersion, process.env.GITHUB_TOKEN
);
expect(fs.readFile).not.toHaveBeenCalled();
});
});
});

3465
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -19,16 +19,16 @@
"keywords": [], "keywords": [],
"author": "", "author": "",
"dependencies": { "dependencies": {
"@actions/core": "1.10.1", "@actions/core": "2.0.1",
"@actions/exec": "1.1.1", "@actions/exec": "2.0.0",
"@actions/io": "1.1.3", "@actions/io": "2.0.0",
"@actions/tool-cache": "2.0.1", "@actions/tool-cache": "2.0.2",
"semver": "7.5.4" "semver": "7.7.3"
}, },
"devDependencies": { "devDependencies": {
"@vercel/ncc": "0.38.1", "@vercel/ncc": "0.38.4",
"husky": "8.0.3", "husky": "9.1.7",
"jest": "29.7.0", "jest": "30.2.0",
"semistandard": "17.0.0" "semistandard": "17.0.0"
}, },
"semistandard": { "semistandard": {

View file

@ -9,7 +9,8 @@
* *
* @example * @example
* // Instantiate a new listener * // Instantiate a new listener
* const listener = new OutputListener(); * // stream is used to write the data before waiting for the listener to complete
* const listener = new OutputListener(stream);
* // Register listener against STDOUT stream * // Register listener against STDOUT stream
* await exec.exec('ls', ['-ltr'], { * await exec.exec('ls', ['-ltr'], {
* listeners: { * listeners: {
@ -20,12 +21,14 @@
* console.log(listener.contents); * console.log(listener.contents);
*/ */
class OutputListener { class OutputListener {
constructor () { constructor (stream) {
this._buff = []; this._buff = [];
this._stream = stream;
} }
get listener () { get listener () {
const listen = function listen (data) { const listen = function listen (data) {
this._stream.write(data);
this._buff.push(data); this._buff.push(data);
}; };
return listen.bind(this); return listen.bind(this);

View file

@ -4,14 +4,18 @@
*/ */
const OutputListener = require('../lib/output-listener'); const OutputListener = require('../lib/output-listener');
const { PassThrough } = require('stream');
describe('output-listener', () => { describe('output-listener', () => {
it('receives and exposes data', () => { it('receives and exposes data', () => {
const listener = new OutputListener(); const stream = new PassThrough();
const listener = new OutputListener(stream);
const listen = listener.listener; const listen = listener.listener;
listen(Buffer.from('foo')); listen(Buffer.from('foo'));
expect(stream.read()).toEqual(Buffer.from('foo'));
listen(Buffer.from('bar')); listen(Buffer.from('bar'));
expect(stream.read()).toEqual(Buffer.from('bar'));
listen(Buffer.from('baz')); listen(Buffer.from('baz'));
expect(stream.read()).toEqual(Buffer.from('baz'));
expect(listener.contents).toEqual('foobarbaz'); expect(listener.contents).toEqual('foobarbaz');
}); });
}); });

View file

@ -22,8 +22,8 @@ async function checkTofu () {
await checkTofu(); await checkTofu();
// Create listeners to receive output (in memory) as well // Create listeners to receive output (in memory) as well
const stdout = new OutputListener(); const stdout = new OutputListener(process.stdout);
const stderr = new OutputListener(); const stderr = new OutputListener(process.stderr);
const listeners = { const listeners = {
stdout: stdout.listener, stdout: stdout.listener,
stderr: stderr.listener stderr: stderr.listener
@ -33,13 +33,10 @@ async function checkTofu () {
const args = process.argv.slice(2); const args = process.argv.slice(2);
const options = { const options = {
listeners, listeners,
ignoreReturnCode: true ignoreReturnCode: true,
silent: true // don't print "[command...]" into stdout: https://github.com/actions/toolkit/issues/649
}; };
const exitCode = await exec(pathToCLI, args, options); const exitCode = await exec(pathToCLI, args, options);
core.debug(`OpenTofu exited with code ${exitCode}.`);
core.debug(`stdout: ${stdout.contents}`);
core.debug(`stderr: ${stderr.contents}`);
core.debug(`exitcode: ${exitCode}`);
// Set outputs, result, exitcode, and stderr // Set outputs, result, exitcode, and stderr
core.setOutput('stdout', stdout.contents); core.setOutput('stdout', stdout.contents);