diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b057d29..36f179c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,3 +64,47 @@ jobs: - name: Print Output id: output run: echo "${{ steps.test-action.outputs.gop-version }}" + + test-versions: + name: Gop Versions Test + + strategy: + matrix: + gop-version: ['1.1.7', '', 'latest', 'main', 'v1.0'] + include: + - gop-version: '1.1.7' + gop-version-verified: 'true' + - gop-version: '' + gop-version-verified: 'true' + - gop-version: 'latest' + gop-version-verified: 'true' + - gop-version: 'main' + gop-version-verified: 'false' + - gop-version: 'v1.0' + gop-version-verified: 'false' + + runs-on: ubuntu-latest + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Test Gop Version + id: test-gop-version + uses: ./ + with: + gop-version: ${{ matrix.gop-version }} + + - name: Test version verified + env: + VERIFIED: ${{ matrix.gop-version-verified }} + GOP_VERSION: ${{ matrix.gop-version }} + run: | + echo "gop-version: $GOP_VERSION" + echo "gop-version-verified: $VERIFIED" + if [[ "$VERIFIED" != "$VERIFIED" ]]; then + echo "gop-version-verified does not match expected value" + echo "expected: $VERIFIED, got: $VERIFIED" + exit 1 + fi diff --git a/action.yml b/action.yml index f1b24f5..d739c56 100644 --- a/action.yml +++ b/action.yml @@ -43,6 +43,10 @@ outputs: gop-version: description: 'The installed Go+ version. Useful when given a version range as input.' + gop-version-verified: + description: + Whether the installed Go+ version checked, true if the installed version + is in the tags, false otherwise. go-version: description: 'The installed Go version. Useful when given a version range as input.' diff --git a/dist/index.js b/dist/index.js index b03a5f9..ffa68f7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -6020,7 +6020,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.parseGopVersionFile = exports.installGop = void 0; +exports.parseGopVersionFile = exports.selectVersion = exports.installGop = void 0; const core = __importStar(__nccwpck_require__(2186)); const semver = __importStar(__nccwpck_require__(1383)); const fs_1 = __importDefault(__nccwpck_require__(7147)); @@ -6035,24 +6035,40 @@ const GOPLUS_REPO = 'https://github.com/goplus/gop.git'; async function installGop() { try { const versionSpec = resolveVersionInput() || ''; - const versions = semver.rsort(fetchVersions().filter(v => semver.valid(v))); + const tagVersions = semver.rsort(fetchTags().filter(v => semver.valid(v))); let version = null; if (!versionSpec || versionSpec === 'latest') { - version = versions[0]; + version = tagVersions[0]; core.warning(`No gop-version specified, using latest version: ${version}`); } else { - version = semver.maxSatisfying(versions, versionSpec); + version = semver.maxSatisfying(tagVersions, versionSpec); + if (!version) { + core.warning(`No gop-version found that satisfies '${versionSpec}', trying branches...`); + const branchVersions = fetchBranches(); + if (!branchVersions.includes(versionSpec)) { + throw new Error(`No gop-version found that satisfies '${versionSpec}' in branches or tags`); + } + version = ''; + } } - if (!version) { - throw new Error(`Unable to find a version that satisfies the version spec '${versionSpec}'`); + let checkoutVersion = ''; + if (version) { + core.info(`Selected version ${version} by spec ${versionSpec}`); + checkoutVersion = `v${version}`; + core.setOutput('gop-version-verified', true); + } + else { + core.warning(`Unable to find a version that satisfies the version spec '${versionSpec}', trying branches...`); + checkoutVersion = versionSpec; + core.setOutput('gop-version-verified', false); } - core.info(`Selected version ${version} by spec ${versionSpec}`); - const tagVersion = `v${version}`; - const gopDir = clone(tagVersion); + const gopDir = cloneBranchOrTag(checkoutVersion); install(gopDir); - test(tagVersion); - core.setOutput('gop-version', version); + if (version) { + checkVersion(version); + } + core.setOutput('gop-version', gopVersion()); } catch (error) { // Fail the workflow run if an error occurs @@ -6061,7 +6077,15 @@ async function installGop() { } } exports.installGop = installGop; -function clone(versionSpec) { +function selectVersion(versions, versionSpec) { + const sortedVersions = semver.rsort(versions.filter(v => semver.valid(v))); + if (!versionSpec || versionSpec === 'latest') { + return sortedVersions[0]; + } + return semver.maxSatisfying(sortedVersions, versionSpec); +} +exports.selectVersion = selectVersion; +function cloneBranchOrTag(versionSpec) { // git clone https://github.com/goplus/gop.git with tag $versionSpec to $HOME/workdir/gop const workDir = path_1.default.join(os_1.default.homedir(), 'workdir'); if (fs_1.default.existsSync(workDir)) { @@ -6088,16 +6112,20 @@ function install(gopDir) { core.addPath(bin); core.info('gop installed'); } -function test(versionSpec) { +function checkVersion(versionSpec) { core.info(`Testing gop ${versionSpec} ...`); - const out = (0, child_process_1.execSync)('gop env GOPVERSION', { env: process.env }); - const actualVersion = out.toString().trim(); + const actualVersion = gopVersion(); if (actualVersion !== versionSpec) { throw new Error(`Installed gop version ${actualVersion} does not match expected version ${versionSpec}`); } core.info(`Installed gop version ${actualVersion}`); + return actualVersion; } -function fetchVersions() { +function gopVersion() { + const out = (0, child_process_1.execSync)('gop env GOPVERSION', { env: process.env }); + return out.toString().trim().replace(/^v/, ''); +} +function fetchTags() { const cmd = `git -c versionsort.suffix=- ls-remote --tags --sort=v:refname ${GOPLUS_REPO}`; const out = (0, child_process_1.execSync)(cmd).toString(); const versions = out @@ -6107,6 +6135,15 @@ function fetchVersions() { .map(s => s.replace(/^v/, '')); return versions; } +function fetchBranches() { + const cmd = `git -c versionsort.suffix=- ls-remote --heads --sort=v:refname ${GOPLUS_REPO}`; + const out = (0, child_process_1.execSync)(cmd).toString(); + const versions = out + .split('\n') + .filter(s => s) + .map(s => s.split('\t')[1].replace('refs/heads/', '')); + return versions; +} function resolveVersionInput() { let version = process.env['INPUT_GOP_VERSION']; const versionFilePath = process.env['INPUT_GOP_VERSION_FILE']; diff --git a/src/install-gop.ts b/src/install-gop.ts index 7471aef..4c657c8 100644 --- a/src/install-gop.ts +++ b/src/install-gop.ts @@ -14,33 +14,63 @@ const GOPLUS_REPO = 'https://github.com/goplus/gop.git' export async function installGop(): Promise { try { const versionSpec = resolveVersionInput() || '' - const versions = semver.rsort(fetchVersions().filter(v => semver.valid(v))) + const tagVersions = semver.rsort(fetchTags().filter(v => semver.valid(v))) let version: string | null = null if (!versionSpec || versionSpec === 'latest') { - version = versions[0] + version = tagVersions[0] core.warning(`No gop-version specified, using latest version: ${version}`) } else { - version = semver.maxSatisfying(versions, versionSpec) + version = semver.maxSatisfying(tagVersions, versionSpec) + if (!version) { + core.warning( + `No gop-version found that satisfies '${versionSpec}', trying branches...` + ) + const branchVersions = fetchBranches() + if (!branchVersions.includes(versionSpec)) { + throw new Error( + `No gop-version found that satisfies '${versionSpec}' in branches or tags` + ) + } + version = '' + } } - if (!version) { - throw new Error( - `Unable to find a version that satisfies the version spec '${versionSpec}'` + let checkoutVersion = '' + if (version) { + core.info(`Selected version ${version} by spec ${versionSpec}`) + checkoutVersion = `v${version}` + core.setOutput('gop-version-verified', true) + } else { + core.warning( + `Unable to find a version that satisfies the version spec '${versionSpec}', trying branches...` ) + checkoutVersion = versionSpec + core.setOutput('gop-version-verified', false) } - core.info(`Selected version ${version} by spec ${versionSpec}`) - const tagVersion = `v${version}` - const gopDir = clone(tagVersion) + const gopDir = cloneBranchOrTag(checkoutVersion) install(gopDir) - test(tagVersion) - core.setOutput('gop-version', version) + if (version) { + checkVersion(version) + } + core.setOutput('gop-version', gopVersion()) } catch (error) { // Fail the workflow run if an error occurs if (error instanceof Error) core.setFailed(error.message) } } -function clone(versionSpec: string): string { +export function selectVersion( + versions: string[], + versionSpec?: string +): string | null { + const sortedVersions = semver.rsort(versions.filter(v => semver.valid(v))) + if (!versionSpec || versionSpec === 'latest') { + return sortedVersions[0] + } + return semver.maxSatisfying(sortedVersions, versionSpec) +} + +function cloneBranchOrTag(versionSpec: string): string { // git clone https://github.com/goplus/gop.git with tag $versionSpec to $HOME/workdir/gop const workDir = path.join(os.homedir(), 'workdir') if (fs.existsSync(workDir)) { @@ -69,19 +99,24 @@ function install(gopDir: string): void { core.info('gop installed') } -function test(versionSpec: string): void { +function checkVersion(versionSpec: string): string { core.info(`Testing gop ${versionSpec} ...`) - const out = execSync('gop env GOPVERSION', { env: process.env }) - const actualVersion = out.toString().trim() + const actualVersion = gopVersion() if (actualVersion !== versionSpec) { throw new Error( `Installed gop version ${actualVersion} does not match expected version ${versionSpec}` ) } core.info(`Installed gop version ${actualVersion}`) + return actualVersion } -function fetchVersions(): string[] { +function gopVersion(): string { + const out = execSync('gop env GOPVERSION', { env: process.env }) + return out.toString().trim().replace(/^v/, '') +} + +function fetchTags(): string[] { const cmd = `git -c versionsort.suffix=- ls-remote --tags --sort=v:refname ${GOPLUS_REPO}` const out = execSync(cmd).toString() const versions = out @@ -92,6 +127,16 @@ function fetchVersions(): string[] { return versions } +function fetchBranches(): string[] { + const cmd = `git -c versionsort.suffix=- ls-remote --heads --sort=v:refname ${GOPLUS_REPO}` + const out = execSync(cmd).toString() + const versions = out + .split('\n') + .filter(s => s) + .map(s => s.split('\t')[1].replace('refs/heads/', '')) + return versions +} + function resolveVersionInput(): string | undefined { let version = process.env['INPUT_GOP_VERSION'] const versionFilePath = process.env['INPUT_GOP_VERSION_FILE']