From da3271e0a2f8b8552a91e37cf85d03622c328ab7 Mon Sep 17 00:00:00 2001 From: Janos <86970079+janosdebugs@users.noreply.github.com> Date: Tue, 30 Jan 2024 19:49:40 +0100 Subject: [PATCH] Adding Forgejo support (#23) Signed-off-by: Janos Bonic <86970079+janosdebugs@users.noreply.github.com> Co-authored-by: Bence Santha --- README.md | 3 ++- action.yml | 4 ++++ dist/index.js | 21 ++++++++++++++------- lib/releases.js | 13 +++++++------ lib/setup-tofu.js | 8 +++++++- lib/test/releases.test.js | 4 ++-- 6 files changed, 36 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 5378ca1..c6dbd4e 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ A specific version of OpenTofu CLI can be installed: steps: - uses: opentofu/setup-opentofu@v1 with: - tofu_version: 1.6.0-alpha1 + tofu_version: 1.6.0 ``` Credentials for Terraform Cloud ([app.terraform.io](https://app.terraform.io/)) can be configured: @@ -257,6 +257,7 @@ The action supports the following inputs: - `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 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 diff --git a/action.yml b/action.yml index a8e61a9..2a0497d 100644 --- a/action.yml +++ b/action.yml @@ -17,6 +17,10 @@ inputs: 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' 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: stdout: description: 'The STDOUT stream of the call to the `tofu` binary.' diff --git a/dist/index.js b/dist/index.js index 6c2709a..d81e32f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -33,7 +33,7 @@ class Release { * * @return {Array} Releases. */ -async function fetchReleases () { +async function fetchReleases (githubToken) { const url = 'https://api.github.com/repos/opentofu/opentofu/releases'; const headers = { @@ -41,8 +41,8 @@ async function fetchReleases () { 'X-GitHub-Api-Version': '2022-11-28' }; - if (process.env.GITHUB_TOKEN) { - headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; + if (githubToken) { + headers.Authorization = `Bearer ${githubToken}`; } const resp = await fetch(url, { @@ -50,7 +50,7 @@ async function fetchReleases () { }); if (!resp.ok) { - throw new Error('failed fetching releases'); + throw new Error('failed fetching releases (' + resp.status + ')'); } const releasesMeta = await resp.json(); @@ -72,10 +72,11 @@ async function findLatestVersionInRange (versions, range) { * Fetches the release given the 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. * @return {Release} Release. */ -async function getRelease (version, fetchReleasesFn = fetchReleases) { +async function getRelease (version, githubToken, fetchReleasesFn = fetchReleases) { const latestVersionLabel = 'latest'; const versionsRange = semver.validRange(version, { prerelease: true, loose: true }); @@ -83,7 +84,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'); } - const releases = await fetchReleasesFn(); + const releases = await fetchReleasesFn(githubToken); if (releases === null || releases.length === 0) { throw new Error('No tofu releases found, please contact OpenTofu'); @@ -251,13 +252,19 @@ async function run () { const credentialsHostname = core.getInput('cli_config_credentials_hostname'); const credentialsToken = core.getInput('cli_config_credentials_token'); 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; + } // Gather OS details const osPlatform = os.platform(); const osArch = os.arch(); 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 arch = mapArch(osArch); const build = release.getBuild(platform, arch); diff --git a/lib/releases.js b/lib/releases.js index 0947a53..b49f31f 100644 --- a/lib/releases.js +++ b/lib/releases.js @@ -27,7 +27,7 @@ class Release { * * @return {Array} Releases. */ -async function fetchReleases () { +async function fetchReleases (githubToken) { const url = 'https://api.github.com/repos/opentofu/opentofu/releases'; const headers = { @@ -35,8 +35,8 @@ async function fetchReleases () { 'X-GitHub-Api-Version': '2022-11-28' }; - if (process.env.GITHUB_TOKEN) { - headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; + if (githubToken) { + headers.Authorization = `Bearer ${githubToken}`; } const resp = await fetch(url, { @@ -44,7 +44,7 @@ async function fetchReleases () { }); if (!resp.ok) { - throw new Error('failed fetching releases'); + throw new Error('failed fetching releases (' + resp.status + ')'); } const releasesMeta = await resp.json(); @@ -66,10 +66,11 @@ async function findLatestVersionInRange (versions, range) { * Fetches the release given the 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. * @return {Release} Release. */ -async function getRelease (version, fetchReleasesFn = fetchReleases) { +async function getRelease (version, githubToken, fetchReleasesFn = fetchReleases) { const latestVersionLabel = 'latest'; const versionsRange = semver.validRange(version, { prerelease: true, loose: true }); @@ -77,7 +78,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'); } - const releases = await fetchReleasesFn(); + const releases = await fetchReleasesFn(githubToken); if (releases === null || releases.length === 0) { throw new Error('No tofu releases found, please contact OpenTofu'); diff --git a/lib/setup-tofu.js b/lib/setup-tofu.js index f21fb6c..37f56e1 100644 --- a/lib/setup-tofu.js +++ b/lib/setup-tofu.js @@ -132,13 +132,19 @@ async function run () { const credentialsHostname = core.getInput('cli_config_credentials_hostname'); const credentialsToken = core.getInput('cli_config_credentials_token'); 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; + } // Gather OS details const osPlatform = os.platform(); const osArch = os.arch(); 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 arch = mapArch(osArch); const build = release.getBuild(platform, arch); diff --git a/lib/test/releases.test.js b/lib/test/releases.test.js index 57d395d..eb348c8 100644 --- a/lib/test/releases.test.js +++ b/lib/test/releases.test.js @@ -197,7 +197,7 @@ describe('getRelease', () => { ] )('happy path: getRelease(\'%s\') -> \'%s\'', async (input, 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); }); @@ -210,7 +210,7 @@ describe('getRelease', () => { ] )('unhappy path: getRelease(\'%s\') -> throw Error(\'%s\')', async (input, wantErrorMessage, mockFetchReleasesFn) => { try { - await pkg.getRelease(input, mockFetchReleasesFn); + await pkg.getRelease(input, '', mockFetchReleasesFn); expect(true).toBe(false); } catch (e) { expect(e.message).toBe(wantErrorMessage);