diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index dbad277c1..03f0de54b 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -142,6 +142,28 @@ jobs: run: __tests__/verify-go.sh 1.21 shell: bash + auto-detect-go-mod: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] + steps: + - uses: actions/checkout@v6 + - name: Create go.mod in workspace root + run: | + cat > go.mod << 'EOF' + module github.com/actions/setup-go + + go 1.21 + EOF + shell: bash + - name: Setup Go with auto-detection + uses: ./ + - name: Verify go version + run: __tests__/verify-go.sh 1.21 + shell: bash + go-version-file-with-tool-versions: runs-on: ${{ matrix.os }} strategy: diff --git a/__tests__/setup-go.test.ts b/__tests__/setup-go.test.ts index 5015e9165..03b26f2f2 100644 --- a/__tests__/setup-go.test.ts +++ b/__tests__/setup-go.test.ts @@ -1112,6 +1112,31 @@ use . expect(process.env).toHaveProperty('GOTOOLCHAIN', 'local'); }); + describe('auto-detect go.mod', () => { + it('uses go.mod from workspace root when no inputs provided', async () => { + existsSpy.mockImplementation((filePath: string) => { + return filePath === 'go.mod'; + }); + readFileSpy.mockImplementation(() => + Buffer.from('module test\n\ngo 1.20') + ); + + await main.run(); + + expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.20'); + }); + + it('uses pre-installed Go when no inputs and no go.mod exists', async () => { + existsSpy.mockImplementation(() => false); + + await main.run(); + + expect(logSpy).toHaveBeenCalledWith( + '[warning]go-version input was not specified. The action will try to use pre-installed version.' + ); + }); + }); + describe('go-download-base-url', () => { it('downloads a version from custom base URL using version listing', async () => { os.platform = 'linux'; diff --git a/action.yml b/action.yml index 74a4e7e9f..821bd6195 100644 --- a/action.yml +++ b/action.yml @@ -5,7 +5,7 @@ inputs: go-version: description: 'The Go version to download (if necessary) and use. Supports semver spec and ranges. Be sure to enclose this option in single quotation marks.' go-version-file: - description: 'Path to the go.mod, go.work, .go-version, or .tool-versions file.' + description: 'Path to the go.mod, go.work, .go-version, or .tool-versions file. If not specified, the action will automatically use go.mod from the workspace root if it exists.' check-latest: description: 'Set this option to true if you want the action to always check for the latest available version that satisfies the version spec' default: false diff --git a/dist/setup/index.js b/dist/setup/index.js index 796803ef3..3e35adc90 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -77741,6 +77741,9 @@ function resolveVersionInput() { } version = installer.parseGoVersionFile(versionFilePath); } + if (!version && fs_1.default.existsSync('go.mod')) { + version = installer.parseGoVersionFile('go.mod'); + } return version; } function setGoToolchain() { diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 91e8ffa9d..1a4196249 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -168,6 +168,18 @@ jobs: If both the `go-version` and the `go-version-file` inputs are provided then the `go-version` input is used. The `.tool-versions` file supports version specifications in accordance with asdf standards, adhering to Semantic Versioning ([semver](https://semver.org)). +### Automatic go.mod detection + +If neither `go-version` nor `go-version-file` is specified, the action will automatically look for a `go.mod` file in the repository root and use the Go version specified in it. This simplifies workflows for projects that already have a `go.mod` file. + +```yaml +steps: + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 + # Automatically uses go.mod from repository root + - run: go version +``` + ```yaml steps: - uses: actions/checkout@v6 diff --git a/src/main.ts b/src/main.ts index e578ed946..045d3ba33 100644 --- a/src/main.ts +++ b/src/main.ts @@ -170,6 +170,10 @@ function resolveVersionInput(): string { version = installer.parseGoVersionFile(versionFilePath); } + if (!version && fs.existsSync('go.mod')) { + version = installer.parseGoVersionFile('go.mod'); + } + return version; }