Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add go-version-from-file option #62

Merged
merged 15 commits into from
May 12, 2022
62 changes: 62 additions & 0 deletions __tests__/setup-go.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('setup-go', () => {
let dbgSpy: jest.SpyInstance;
let whichSpy: jest.SpyInstance;
let existsSpy: jest.SpyInstance;
let readFileSpy: jest.SpyInstance;
let mkdirpSpy: jest.SpyInstance;
let execSpy: jest.SpyInstance;
let getManifestSpy: jest.SpyInstance;
Expand Down Expand Up @@ -60,6 +61,7 @@ describe('setup-go', () => {
// io
whichSpy = jest.spyOn(io, 'which');
existsSpy = jest.spyOn(fs, 'existsSync');
readFileSpy = jest.spyOn(fs, 'readFileSync');
mkdirpSpy = jest.spyOn(io, 'mkdirP');

// gets
Expand Down Expand Up @@ -556,4 +558,64 @@ describe('setup-go', () => {
it('does not convert exact versions', async () => {
expect(im.makeSemver('1.13.1')).toBe('1.13.1');
});

describe('go-version-file', () => {
it('reads version from go.mod', async () => {
inputs['go-version-file'] = 'go.mod';
const content = `module example.com/mymodule

go 1.14

require (
example.com/othermodule v1.2.3
example.com/thismodule v1.2.3
example.com/thatmodule v1.2.3
)

replace example.com/thatmodule => ../thatmodule
exclude example.com/thismodule v1.3.0
`;
readFileSpy.mockImplementation(() => Buffer.from(content));

await main.run();

expect(logSpy).toHaveBeenCalledWith('Setup go stable version spec 1.14');
});

it('reads version from .go-version', async () => {
inputs['go-version-file'] = '.go-version';
readFileSpy.mockImplementation(() => Buffer.from(`1.13.0${osm.EOL}`));

await main.run();

expect(logSpy).toHaveBeenCalledWith(
'Setup go stable version spec 1.13.0'
);
});

it('is overwritten by go-version', async () => {
inputs['go-version'] = '1.13.1';
inputs['go-version-file'] = '.go-version';
readFileSpy.mockImplementation(() => Buffer.from(`1.13.0${osm.EOL}`));

await main.run();

expect(logSpy).toHaveBeenCalledWith(
'Setup go stable version spec 1.13.1'
);
});

it('reports a read failure', async () => {
const versionFilePath = '.go-version';
inputs['go-version-file'] = versionFilePath;
const errMsg = `ENOENT: no such file or directory, open '${versionFilePath}'`;
readFileSpy.mockImplementation(() => {
throw new Error(errMsg);
});

await main.run();

expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`);
});
});
});
2 changes: 2 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ author: 'GitHub'
inputs:
go-version:
description: 'The Go version to download (if necessary) and use. Supports semver spec and ranges.'
go-version-from-file:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
go-version-from-file:
go-version-file:

description: Path to the file with the Go version. go-version overwrites this.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: Path to the file with the Go version. go-version overwrites this.
description: 'Path to the go.mod file.'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IvanZosimov FWIW as an end user I would find the original description more accurate. While I guess none of us can predict what % of users will end up specifying go.mod and what other % .go-version, but I assume (hope) that the intention is to support both and so the description should reflect that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @radeksimko 👋 ! Thank you, that's definitely a good point! We are going to update setup-go documentation with the new chapter related to this functionality with a more broad description of the input.

stable:
description: 'Whether to download only stable versions'
default: 'true'
Expand Down
23 changes: 21 additions & 2 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,7 @@ function run() {
// versionSpec is optional. If supplied, install / use from the tool cache
// If not supplied then problem matchers will still be setup. Useful for self-hosted.
//
let versionSpec = core.getInput('go-version');
const versionSpec = resolveVersionInput();
// stable will be true unless false is the exact input
// since getting unstable versions should be explicit
let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
Expand Down Expand Up @@ -1500,6 +1500,17 @@ function isGhes() {
const ghUrl = new url_1.URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
}
function resolveVersionInput() {
let version = core.getInput('go-version');
const versionFilePath = core.getInput('go-version-file');
if (version) {
return version;
}
if (versionFilePath) {
version = installer.parseGoVersionFile(fs_1.default.readFileSync(versionFilePath).toString(), path_1.default.basename(versionFilePath) === 'go.mod');
}
return version;
}


/***/ }),
Expand Down Expand Up @@ -4935,7 +4946,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeSemver = exports.getVersionsDist = exports.findMatch = exports.getInfoFromManifest = exports.extractGoArchive = exports.getGo = void 0;
exports.parseGoVersionFile = exports.makeSemver = exports.getVersionsDist = exports.findMatch = exports.getInfoFromManifest = exports.extractGoArchive = exports.getGo = void 0;
const tc = __importStar(__webpack_require__(533));
const core = __importStar(__webpack_require__(470));
const path = __importStar(__webpack_require__(622));
Expand Down Expand Up @@ -5138,6 +5149,14 @@ function makeSemver(version) {
return `${verPart}${prereleasePart}`;
}
exports.makeSemver = makeSemver;
function parseGoVersionFile(contents, isMod) {
if (!isMod) {
return contents.trim();
}
const match = contents.match(/^go (\d+(\.\d+)*)/m);
return match ? match[1] : '';
}
exports.parseGoVersionFile = parseGoVersionFile;


/***/ }),
Expand Down
9 changes: 9 additions & 0 deletions src/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,12 @@ export function makeSemver(version: string): string {

return `${verPart}${prereleasePart}`;
}

export function parseGoVersionFile(contents: string, isMod: boolean): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the input go-version-file should contain the path to a go.mod file (we'll deliberately ask our customers to put there a path to go.mod file ), I'd suggest not using isMod parameter in this function and don't check whether path refers to 'go.mod' file.

if (!isMod) {
return contents.trim();
}

const match = contents.match(/^go (\d+(\.\d+)*)/m);
return match ? match[1] : '';
}
20 changes: 19 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function run() {
// versionSpec is optional. If supplied, install / use from the tool cache
// If not supplied then problem matchers will still be setup. Useful for self-hosted.
//
let versionSpec = core.getInput('go-version');
const versionSpec = resolveVersionInput();

// stable will be true unless false is the exact input
// since getting unstable versions should be explicit
Expand Down Expand Up @@ -90,3 +90,21 @@ function isGhes(): boolean {
);
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
}

function resolveVersionInput(): string {
let version = core.getInput('go-version');
const versionFilePath = core.getInput('go-version-file');

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add here the warning when the user specifies both inputs:

if (version && versionFilePath) {
    core.warning(
      'Both go-version and go-version-file inputs are specified, only go-version will be used'
    );
  }

if (version) {
return version;
}

if (versionFilePath) {
version = installer.parseGoVersionFile(
fs.readFileSync(versionFilePath).toString(),
path.basename(versionFilePath) === 'go.mod'
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest keeping this conditional statement very similar to the one in setup-node action. Otherwise, some important functionality will be lost.


return version;
}