diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index 89fc7b8d3..1fd581c44 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -134,6 +134,22 @@ jobs: run: __tests__/verify-go.sh 1.19 shell: bash + tool-versions-file: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - uses: actions/checkout@v3 + - name: Setup Go and check latest + uses: ./ + with: + tool-versions-file: __tests__/data/.tool-versions + - name: verify go + run: __tests__/verify-go.sh 1.16.3 + shell: bash + setup-versions-from-manifest: name: Setup ${{ matrix.go }} ${{ matrix.os }} runs-on: ${{ matrix.os }} diff --git a/README.md b/README.md index eb4f9dd23..81dcf5a28 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,10 @@ The `go-version` input supports the following syntax: For more information about semantic versioning, please refer to [semver](https://github.com/npm/node-semver) documentation. +The action can also utilize a [`.tool-versions` file](https://asdf-vm.com/manage/configuration.html#tool-versions) +if `go-version` is not specified (`go-version` will take precedence over any `.tool-versions` specified). If the `. +tool-versions` is not in the project root, you can specify its location via the `tool-version-file` input. + ## Using `setup-go` on GHES `setup-go` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Go diff --git a/__tests__/data/.tool-versions b/__tests__/data/.tool-versions new file mode 100644 index 000000000..cce7a1b62 --- /dev/null +++ b/__tests__/data/.tool-versions @@ -0,0 +1,4 @@ +terraform 1.3.7 +golang 1.16.3 +python 3.10.11 +ruby 3.2.1 diff --git a/__tests__/setup-go.test.ts b/__tests__/setup-go.test.ts index cea14f4e8..3a55c53f7 100644 --- a/__tests__/setup-go.test.ts +++ b/__tests__/setup-go.test.ts @@ -957,4 +957,48 @@ use . } ); }); + + describe('tool-versions-file', () => { + const toolVersionsFile = `terraform 1.3.7 +golang 1.16.3 +python 3.10.11 +ruby 3.2.1 +`; + + it('reads version from .tool-versions when specified', async () => { + inputs['tool-versions-file'] = '.special-tool-versions'; + existsSpy.mockImplementation(() => true); + readFileSpy.mockImplementation(() => Buffer.from(toolVersionsFile)); + + await main.run(); + + expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.16.3'); + expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.16.3...'); + expect(logSpy).toHaveBeenCalledWith('matching 1.16.3...'); + }); + + it('is overwritten by go-version param', async () => { + inputs['go-version'] = '1.18.2'; + inputs['tool-versions-file'] = '.special-tool-versions'; + existsSpy.mockImplementation(() => true); + readFileSpy.mockImplementation(() => Buffer.from(toolVersionsFile)); + + await main.run(); + + expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.18.2'); + expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.18.2...'); + expect(logSpy).toHaveBeenCalledWith('matching 1.18.2...'); + }); + + it('uses .tool-versions as a default when no version specified', async () => { + existsSpy.mockImplementation(() => true); + readFileSpy.mockImplementation(() => Buffer.from(toolVersionsFile)); + + await main.run(); + + expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.16.3'); + expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.16.3...'); + expect(logSpy).toHaveBeenCalledWith('matching 1.16.3...'); + }); + }); }); diff --git a/dist/setup/index.js b/dist/setup/index.js index 0dcd2342d..56b4268e6 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -61337,7 +61337,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.resolveStableVersionInput = exports.parseGoVersionFile = exports.makeSemver = exports.getVersionsDist = exports.findMatch = exports.getInfoFromManifest = exports.getManifest = exports.extractGoArchive = exports.getGo = void 0; +exports.resolveStableVersionInput = exports.parseToolVersionsFile = exports.parseGoVersionFile = exports.makeSemver = exports.getVersionsDist = exports.findMatch = exports.getInfoFromManifest = exports.getManifest = exports.extractGoArchive = exports.getGo = void 0; const tc = __importStar(__nccwpck_require__(7784)); const core = __importStar(__nccwpck_require__(2186)); const path = __importStar(__nccwpck_require__(1017)); @@ -61598,6 +61598,12 @@ function parseGoVersionFile(versionFilePath) { return contents.trim(); } exports.parseGoVersionFile = parseGoVersionFile; +function parseToolVersionsFile(toolVersionsPath) { + const contents = fs_1.default.readFileSync(toolVersionsPath).toString(); + const match = contents.match(/^golang (\d+(\.\d+)*)/m); + return match ? match[1] : ''; +} +exports.parseToolVersionsFile = parseToolVersionsFile; function resolveStableVersionDist(versionSpec, arch) { return __awaiter(this, void 0, void 0, function* () { const archFilter = sys.getArch(arch); @@ -61794,18 +61800,32 @@ exports.parseGoVersion = parseGoVersion; function resolveVersionInput() { let version = core.getInput('go-version'); const versionFilePath = core.getInput('go-version-file'); - if (version && versionFilePath) { - core.warning('Both go-version and go-version-file inputs are specified, only go-version will be used'); + let toolVersionsPath = core.getInput('tool-versions-file'); + if (version && (versionFilePath || toolVersionsPath)) { + core.warning('Multiple version inputs are specified, only go-version will be used'); } if (version) { return version; } - if (versionFilePath) { + else if (versionFilePath) { if (!fs_1.default.existsSync(versionFilePath)) { throw new Error(`The specified go version file at: ${versionFilePath} does not exist`); } version = installer.parseGoVersionFile(versionFilePath); } + else { + // in the case of no version specification, reach for .tool-versions + if (toolVersionsPath && !fs_1.default.existsSync(toolVersionsPath)) { + throw new Error(`The specified .tool-versions file at ${toolVersionsPath} does not exist`); + } + if (!toolVersionsPath) { + toolVersionsPath = '.tool-versions'; + if (!fs_1.default.existsSync(toolVersionsPath)) { + throw new Error(`No .tool-versions file was found in the project path. Please specify using tool-versions-file`); + } + } + version = installer.parseToolVersionsFile(toolVersionsPath); + } return version; } diff --git a/src/installer.ts b/src/installer.ts index 013fb6405..2894d3e28 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -366,6 +366,13 @@ export function parseGoVersionFile(versionFilePath: string): string { return contents.trim(); } +export function parseToolVersionsFile(toolVersionsPath: string): string { + const contents = fs.readFileSync(toolVersionsPath).toString(); + + const match = contents.match(/^golang (\d+(\.\d+)*)/m); + return match ? match[1] : ''; +} + async function resolveStableVersionDist(versionSpec: string, arch: string) { const archFilter = sys.getArch(arch); const platFilter = sys.getPlatform(); diff --git a/src/main.ts b/src/main.ts index d3fb857df..8be7c6e6e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -138,24 +138,41 @@ export function parseGoVersion(versionString: string): string { function resolveVersionInput(): string { let version = core.getInput('go-version'); const versionFilePath = core.getInput('go-version-file'); + let toolVersionsPath = core.getInput('tool-versions-file'); - if (version && versionFilePath) { + if (version && (versionFilePath || toolVersionsPath)) { core.warning( - 'Both go-version and go-version-file inputs are specified, only go-version will be used' + 'Multiple version inputs are specified, only go-version will be used' ); } if (version) { return version; - } - - if (versionFilePath) { + } else if (versionFilePath) { if (!fs.existsSync(versionFilePath)) { throw new Error( `The specified go version file at: ${versionFilePath} does not exist` ); } version = installer.parseGoVersionFile(versionFilePath); + } else { + // in the case of no version specification, reach for .tool-versions + if (toolVersionsPath && !fs.existsSync(toolVersionsPath)) { + throw new Error( + `The specified .tool-versions file at ${toolVersionsPath} does not exist` + ); + } + + if (!toolVersionsPath) { + toolVersionsPath = '.tool-versions'; + if (!fs.existsSync(toolVersionsPath)) { + throw new Error( + `No .tool-versions file was found in the project path. Please specify using tool-versions-file` + ); + } + } + + version = installer.parseToolVersionsFile(toolVersionsPath); } return version;