From a5f9b05d2d216f63e13859e0d847461041025775 Mon Sep 17 00:00:00 2001 From: Priya Gupta <147705955+priyagupta108@users.noreply.github.com> Date: Mon, 26 Jan 2026 22:29:03 +0530 Subject: [PATCH] Update default Go module caching to use go.mod (#705) * Update module cache to use go.mod as key * Fix typo * Revise breaking changes in README for V6 Updated breaking changes section with enhanced formatting and clarified toolchain management details. --- README.md | 24 +++---- __tests__/cache-restore.test.ts | 113 ++++++++++++++++---------------- __tests__/cache-utils.test.ts | 4 +- action.yml | 2 +- dist/cache-save/index.js | 2 +- dist/setup/index.js | 6 +- src/cache-restore.ts | 4 +- src/package-managers.ts | 2 +- 8 files changed, 77 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index e2bad30..7e939ad 100644 --- a/README.md +++ b/README.md @@ -24,24 +24,18 @@ steps: ### V6 Changes -#### Node Runtime Upgrade +**Node Runtime Upgrade** - **Upgraded from Node 20 to Node 24** - ⚠️ **Action Required**: Ensure your runner is on version v2.327.1 or later for compatibility - See [Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1) for more details -#### Enhanced Go Toolchain Management +**Enhanced Go Toolchain Management** -V6 introduces significant improvements for reliable and consistent Go version selection: +V6 introduces significant improvements for reliable and consistent Go version selection. Supports both `go` and `toolchain` directives in `go.mod`. If the `toolchain` directive is present, its version is used; otherwise, the action falls back to the go directive. + +**Cache Key Update** -**Toolchain Directive Support** -Now correctly interprets both `go` and `toolchain` directives from `go.mod`: -```go -go 1.23.0 // Minimum required version -toolchain go1.23.2 // V6 uses this exact version -``` - -**Intelligent Caching** -Cache keys now incorporate the `toolchain` directive version from `go.mod`, eliminating cache conflicts when switching between different toolchain versions within the same Go minor release. +By default, caching for Go modules now relies on `go.mod`. To use `go.sum`, configure the `cache-dependency-path` input. For more details, see the [full release notes](https://github.com/actions/setup-go/releases/tag/v6.0.0). @@ -257,7 +251,7 @@ The action features integrated caching for Go modules and build outputs. Built o #### Automatic Caching -Default behavior: Searches for `go.sum` in the repository root and uses its hash for the cache key. +Default behavior: Searches for `go.mod` in the repository root and uses its hash for the cache key. ```yaml steps: @@ -368,7 +362,7 @@ jobs: path: | ${{ env.GO_MOD_CACHE }} ${{ env.GO_BUILD_CACHE }} - key: setup-go-${{ runner.os }}-${{ env.ARCH }}-${{ env.CACHE_OS_SUFFIX }}go-${{ steps.setup-go.outputs.go-version }}-${{ hashFiles('**/go.sum') }} + key: setup-go-${{ runner.os }}-${{ env.ARCH }}-${{ env.CACHE_OS_SUFFIX }}go-${{ steps.setup-go.outputs.go-version }}-${{ hashFiles('**/go.mod') }} - name: Download modules run: go mod download - name: Build @@ -483,4 +477,4 @@ Contributions are welcome! See our [Contributor's Guide](docs/contributors.md) f ## Code of Conduct -👋 Be nice. See our [Code of Conduct](CODE_OF_CONDUCT.md). \ No newline at end of file +👋 Be nice. See our [Code of Conduct](CODE_OF_CONDUCT.md). diff --git a/__tests__/cache-restore.test.ts b/__tests__/cache-restore.test.ts index 07dc97a..7474312 100644 --- a/__tests__/cache-restore.test.ts +++ b/__tests__/cache-restore.test.ts @@ -1,94 +1,83 @@ import * as cache from '@actions/cache'; import * as core from '@actions/core'; import * as glob from '@actions/glob'; +import fs from 'fs'; import * as cacheRestore from '../src/cache-restore'; import * as cacheUtils from '../src/cache-utils'; import {PackageManagerInfo} from '../src/package-managers'; describe('restoreCache', () => { - //Arrange - const hashFilesSpy = jest.spyOn(glob, 'hashFiles'); - const getCacheDirectoryPathSpy = jest.spyOn( - cacheUtils, - 'getCacheDirectoryPath' - ); - const restoreCacheSpy = jest.spyOn(cache, 'restoreCache'); - const infoSpy = jest.spyOn(core, 'info'); - const setOutputSpy = jest.spyOn(core, 'setOutput'); + let hashFilesSpy: jest.SpyInstance; + let getCacheDirectoryPathSpy: jest.SpyInstance; + let restoreCacheSpy: jest.SpyInstance; + let infoSpy: jest.SpyInstance; + let setOutputSpy: jest.SpyInstance; const versionSpec = '1.13.1'; const packageManager = 'default'; const cacheDependencyPath = 'path'; + let originalWorkspace: string | undefined; + beforeEach(() => { + originalWorkspace = process.env.GITHUB_WORKSPACE; + process.env.GITHUB_WORKSPACE = '/test/workspace'; + //Arrange + hashFilesSpy = jest.spyOn(glob, 'hashFiles'); + getCacheDirectoryPathSpy = jest.spyOn(cacheUtils, 'getCacheDirectoryPath'); + restoreCacheSpy = jest.spyOn(cache, 'restoreCache'); + infoSpy = jest.spyOn(core, 'info'); + setOutputSpy = jest.spyOn(core, 'setOutput'); + getCacheDirectoryPathSpy.mockImplementation( (PackageManager: PackageManagerInfo) => { - return new Promise(resolve => { - resolve(['cache_directory_path', 'cache_directory_path']); - }); + return Promise.resolve([ + 'cache_directory_path', + 'cache_directory_path' + ]); } ); }); - it('should throw if dependency file path is not valid', async () => { - //Arrange - hashFilesSpy.mockImplementation((somePath: string) => { - return new Promise(resolve => { - resolve(''); - }); - }); + afterEach(() => { + process.env.GITHUB_WORKSPACE = originalWorkspace; + jest.restoreAllMocks(); + }); - //Act + Assert - await expect(async () => { - await cacheRestore.restoreCache( + it('should throw if dependency file path is not valid', async () => { + // Arrange + hashFilesSpy.mockImplementation(() => Promise.resolve('')); + // Act + Assert + await expect( + cacheRestore.restoreCache( versionSpec, packageManager, cacheDependencyPath - ); - }).rejects.toThrow( + ) + ).rejects.toThrow( 'Some specified paths were not resolved, unable to cache dependencies.' ); }); - it('should inform if cache hit is not occured', async () => { - //Arrange - hashFilesSpy.mockImplementation((somePath: string) => { - return new Promise(resolve => { - resolve('file_hash'); - }); - }); - - restoreCacheSpy.mockImplementation(() => { - return new Promise(resolve => { - resolve(''); - }); - }); - - //Act + Assert + it('should inform if cache hit is not occurred', async () => { + // Arrange + hashFilesSpy.mockImplementation(() => Promise.resolve('file_hash')); + restoreCacheSpy.mockImplementation(() => Promise.resolve('')); + // Act + Assert await cacheRestore.restoreCache( versionSpec, packageManager, cacheDependencyPath ); - expect(infoSpy).toHaveBeenCalledWith(`Cache is not found`); + expect(infoSpy).toHaveBeenCalledWith('Cache is not found'); }); - it('should set output if cache hit is occured', async () => { - //Arrange - hashFilesSpy.mockImplementation((somePath: string) => { - return new Promise(resolve => { - resolve('file_hash'); - }); - }); - - restoreCacheSpy.mockImplementation(() => { - return new Promise(resolve => { - resolve('cache_key'); - }); - }); - - //Act + Assert + it('should set output if cache hit is occurred', async () => { + // Arrange + hashFilesSpy.mockImplementation(() => Promise.resolve('file_hash')); + restoreCacheSpy.mockImplementation(() => Promise.resolve('cache_key')); + // Act + Assert await cacheRestore.restoreCache( versionSpec, packageManager, @@ -96,4 +85,18 @@ describe('restoreCache', () => { ); expect(setOutputSpy).toHaveBeenCalledWith('cache-hit', true); }); + + it('should throw if dependency file is not found in workspace', async () => { + jest.spyOn(fs, 'readdirSync').mockReturnValue(['main.go'] as any); + + await expect( + cacheRestore.restoreCache( + versionSpec, + packageManager + // No cacheDependencyPath + ) + ).rejects.toThrow( + 'Dependencies file is not found in /test/workspace. Supported file pattern: go.mod' + ); + }); }); diff --git a/__tests__/cache-utils.test.ts b/__tests__/cache-utils.test.ts index c848c37..f505ff6 100644 --- a/__tests__/cache-utils.test.ts +++ b/__tests__/cache-utils.test.ts @@ -47,7 +47,7 @@ describe('getPackageManagerInfo', () => { //Arrange const packageManagerName = 'default'; const expectedResult = { - dependencyFilePattern: 'go.sum', + dependencyFilePattern: 'go.mod', cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] }; @@ -73,7 +73,7 @@ describe('getCacheDirectoryPath', () => { const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); const validPackageManager: PackageManagerInfo = { - dependencyFilePattern: 'go.sum', + dependencyFilePattern: 'go.mod', cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] }; diff --git a/action.yml b/action.yml index 36f8204..c5726e1 100644 --- a/action.yml +++ b/action.yml @@ -16,7 +16,7 @@ inputs: description: Used to specify whether caching is needed. Set to true, if you'd like to enable caching. default: true cache-dependency-path: - description: 'Used to specify the path to a dependency file - go.sum' + description: 'Used to specify the path to a dependency file (e.g., go.mod, go.sum)' architecture: description: 'Target architecture for Go to use. Examples: x86, x64. Will use system architecture by default.' outputs: diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index b230dab..ccdac51 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -44277,7 +44277,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.supportedPackageManagers = void 0; exports.supportedPackageManagers = { default: { - dependencyFilePattern: 'go.sum', + dependencyFilePattern: 'go.mod', cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] } }; diff --git a/dist/setup/index.js b/dist/setup/index.js index 3ea5143..5124c96 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -49364,8 +49364,8 @@ const findDependencyFile = (packageManager) => { const dependencyFile = packageManager.dependencyFilePattern; const workspace = process.env.GITHUB_WORKSPACE; const rootContent = fs_1.default.readdirSync(workspace); - const goSumFileExists = rootContent.includes(dependencyFile); - if (!goSumFileExists) { + const goModFileExists = rootContent.includes(dependencyFile); + if (!goModFileExists) { throw new Error(`Dependencies file is not found in ${workspace}. Supported file pattern: ${dependencyFile}`); } return path_1.default.join(workspace, dependencyFile); @@ -50182,7 +50182,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.supportedPackageManagers = void 0; exports.supportedPackageManagers = { default: { - dependencyFilePattern: 'go.sum', + dependencyFilePattern: 'go.mod', cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] } }; diff --git a/src/cache-restore.ts b/src/cache-restore.ts index 18d930b..a18f82d 100644 --- a/src/cache-restore.ts +++ b/src/cache-restore.ts @@ -55,8 +55,8 @@ const findDependencyFile = (packageManager: PackageManagerInfo) => { const workspace = process.env.GITHUB_WORKSPACE!; const rootContent = fs.readdirSync(workspace); - const goSumFileExists = rootContent.includes(dependencyFile); - if (!goSumFileExists) { + const goModFileExists = rootContent.includes(dependencyFile); + if (!goModFileExists) { throw new Error( `Dependencies file is not found in ${workspace}. Supported file pattern: ${dependencyFile}` ); diff --git a/src/package-managers.ts b/src/package-managers.ts index 3547d33..d377de7 100644 --- a/src/package-managers.ts +++ b/src/package-managers.ts @@ -9,7 +9,7 @@ export interface PackageManagerInfo { export const supportedPackageManagers: SupportedPackageManagers = { default: { - dependencyFilePattern: 'go.sum', + dependencyFilePattern: 'go.mod', cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] } };