diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index bd3f75b..a40740a 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -207,6 +207,34 @@ jobs: - name: Check cljstyle version run: cljstyle version + test-zprint: + + strategy: + matrix: + operating-system: [ubuntu-latest, macOS-latest, windows-latest] + + runs-on: ${{ matrix.operating-system }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Prepare java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '8' + + - name: Install zprint + # uses: DeLaGuardo/setup-clojure@master + uses: ./ + with: + zprint: latest + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Check zprint version + run: zprint --version + all-together: runs-on: ubuntu-latest @@ -231,6 +259,7 @@ jobs: bb: latest clj-kondo: latest cljstyle: latest + zprint: latest github-token: ${{ secrets.GITHUB_TOKEN }} - name: Check Clojure CLI @@ -250,3 +279,6 @@ jobs: - name: Check cljstyle version run: cljstyle version + + - name: Check zprint version + run: zprint --version diff --git a/README.md b/README.md index e4751a0..26d3771 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ This action sets up Clojure tools environment for using in GitHub Actions. * Babashka * Clj-kondo * cljstyle +* zprint All three major tools available for MacOS and ubuntu based runners, Leiningen and Clojure CLI also available on Windows @@ -81,6 +82,9 @@ jobs: # cljstyle is not yet available for windows if: ${{ matrix.os != 'windows-latest' }} run: cljstyle version + + - name: Get zprint version + run: zprint --version ``` For more application cases please check [Smoke Test Workflow file](https://github.com/DeLaGuardo/setup-clojure/blob/master/.github/workflows/smoke-tests.yml) diff --git a/__tests__/babashka.test.ts b/__tests__/babashka.test.ts index ada193f..51616b7 100644 --- a/__tests__/babashka.test.ts +++ b/__tests__/babashka.test.ts @@ -19,7 +19,7 @@ const tc: jest.Mocked = _tc as never jest.mock('@actions/core') const core: jest.Mocked = _core as never -describe('tdeps tests', () => { +describe('babashka tests', () => { beforeEach(() => { jest.resetAllMocks() }) diff --git a/__tests__/clj-kondo.test.ts b/__tests__/clj-kondo.test.ts index 80e56a3..c5ea3eb 100644 --- a/__tests__/clj-kondo.test.ts +++ b/__tests__/clj-kondo.test.ts @@ -19,7 +19,7 @@ const tc: jest.Mocked = _tc as never jest.mock('@actions/core') const core: jest.Mocked = _core as never -describe('tdeps tests', () => { +describe('clj-kondo tests', () => { beforeEach(() => { jest.resetAllMocks() }) diff --git a/__tests__/zprint.test.ts b/__tests__/zprint.test.ts new file mode 100644 index 0000000..d4972fe --- /dev/null +++ b/__tests__/zprint.test.ts @@ -0,0 +1,151 @@ +import _os from 'os' +import * as _core from '@actions/core' +import * as _tc from '@actions/tool-cache' +import * as _fs from 'fs/promises' +import * as zprint from '../src/zprint' + +const getJson = jest.fn() +jest.mock('@actions/http-client', () => ({ + HttpClient: function () { + return {getJson} + } +})) + +jest.mock('os') +const os: jest.Mocked = _os as never + +jest.mock('@actions/tool-cache') +const tc: jest.Mocked = _tc as never + +jest.mock('@actions/core') +const core: jest.Mocked = _core as never + +jest.mock('fs/promises') +const fs: jest.Mocked = _fs as never + +describe('zprint tests', () => { + beforeEach(() => { + jest.resetAllMocks() + }) + + describe('getLatestZprint', () => { + it('uses tag_name as latest version', async () => { + getJson.mockResolvedValueOnce({ + result: {tag_name: 'v1.2.3'} + }) + const res = await zprint.getLatestZprint() + expect(res).toBe('1.2.3') + expect(getJson).toHaveBeenCalledWith( + 'https://api.github.com/repos/kkinnear/zprint/releases/latest', + undefined + ) + }) + + it('supports authorization', async () => { + getJson.mockResolvedValueOnce({ + result: {tag_name: 'v1.2.3'} + }) + const res = await zprint.getLatestZprint('token 123') + expect(res).toBe('1.2.3') + expect(getJson).toHaveBeenCalledWith( + 'https://api.github.com/repos/kkinnear/zprint/releases/latest', + {Authorization: 'token 123'} + ) + }) + + it('throws on http client error', async () => { + getJson.mockRejectedValueOnce(new Error('some error')) + await expect(zprint.getLatestZprint()).rejects.toThrow('some error') + }) + + it('throws on wrong client answer', async () => { + getJson.mockResolvedValueOnce({result: {foo: 'bar'}}) + await expect(zprint.getLatestZprint()).rejects.toThrow( + `Can't obtain latest zprint version` + ) + }) + }) + + describe('getArtifactName', () => { + test.each` + platform | artifact + ${'win32'} | ${`zprint-filter-1.2.3`} + ${'darwin'} | ${`zprintm-1.2.3`} + ${'linux'} | ${`zprintl-1.2.3`} + ${'foobar'} | ${`zprintl-1.2.3`} + `('$platform -> $artifact', ({platform, artifact}) => { + os.platform.mockReturnValueOnce(platform as never) + expect(zprint.getArtifactName('1.2.3')).toBe(artifact) + }) + }) + + describe('getArtifactUrl', () => { + test.each` + platform | artifact + ${'win32'} | ${`zprint-filter-1.2.3`} + ${'darwin'} | ${`zprintm-1.2.3`} + ${'linux'} | ${`zprintl-1.2.3`} + ${'foobar'} | ${`zprintl-1.2.3`} + `('$platform -> $artifact', ({platform, artifact}) => { + os.platform.mockReturnValueOnce(platform as never) + expect(zprint.getArtifactUrl('1.2.3')).toBe( + `https://github.com/kkinnear/zprint/releases/download/1.2.3/${artifact}` + ) + }) + }) + + describe('setup', () => { + it('uses cache', async () => { + tc.find.mockReturnValueOnce('/foo/bar') + + await zprint.setup('1.2.3') + + expect(tc.find).toHaveBeenCalledWith('zprint', '1.2.3') + expect(core.addPath).toHaveBeenCalledWith('/foo/bar') + }) + + it('fetches exact version', async () => { + tc.downloadTool.mockResolvedValueOnce('/foo/zprint') + tc.cacheFile.mockResolvedValueOnce('/bar/zprint') + + await zprint.setup('1.2.3', 'token 123') + + expect(tc.find).toHaveBeenCalledWith('zprint', '1.2.3') + expect(tc.downloadTool).toHaveBeenCalledWith( + 'https://github.com/kkinnear/zprint/releases/download/1.2.3/zprintl-1.2.3', + undefined, + 'token 123' + ) + expect(tc.cacheFile).toHaveBeenCalledWith( + '/foo/zprint', + 'zprint', + 'zprint', + '1.2.3' + ) + expect(core.addPath).toHaveBeenCalledWith('/bar/zprint') + }) + + it('fetches latest version', async () => { + getJson.mockResolvedValueOnce({ + result: {tag_name: 'v9.9.9'} + }) + tc.downloadTool.mockResolvedValueOnce('/foo/zprint') + tc.cacheFile.mockResolvedValueOnce('/bar/zprint') + + await zprint.setup('latest', 'token 123') + + expect(getJson).toHaveBeenCalledWith( + 'https://api.github.com/repos/kkinnear/zprint/releases/latest', + {Authorization: 'token 123'} + ) + expect(tc.find).toHaveBeenCalledWith('zprint', '9.9.9') + expect(tc.downloadTool).toHaveBeenCalledWith( + 'https://github.com/kkinnear/zprint/releases/download/9.9.9/zprintl-9.9.9', + undefined, + 'token 123' + ) + expect(tc.cacheFile).toHaveBeenCalledWith('/foo/zprint', 'zprint', 'zprint', '9.9.9') + expect(core.addPath).toHaveBeenCalledWith('/bar/zprint') + }) + }) +}) diff --git a/action.yml b/action.yml index 748369c..4ceaa1a 100644 --- a/action.yml +++ b/action.yml @@ -20,6 +20,8 @@ inputs: description: 'Clj-kondo version to install, `latest` can be used.' cljstyle: description: 'cljstyle version to install, `latest` can be used.' + zprint: + description: 'zprint version to install, `latest` can be used.' github-token: description: >+ To fix rate limit errors, provide `secrets.GITHUB_TOKEN` value to this field. diff --git a/src/entrypoint.ts b/src/entrypoint.ts index 3784b16..ca51d3c 100644 --- a/src/entrypoint.ts +++ b/src/entrypoint.ts @@ -5,6 +5,7 @@ import * as cli from './cli' import * as bb from './babashka' import * as cljKondo from './clj-kondo' import * as cljstyle from './cljstyle' +import * as zprint from './zprint' import * as utils from './utils' export async function run(): Promise { @@ -16,6 +17,7 @@ export async function run(): Promise { const BB_VERSION = core.getInput('bb') const CLJ_KONDO_VERSION = core.getInput('clj-kondo') const CLJSTYLE_VERSION = core.getInput('cljstyle') + const ZPRINT_VERSION = core.getInput('zprint') const githubToken = core.getInput('github-token') const githubAuth = githubToken ? `token ${githubToken}` : undefined @@ -65,6 +67,10 @@ export async function run(): Promise { tools.push(cljstyle.setup(CLJSTYLE_VERSION, githubAuth)) } + if (ZPRINT_VERSION) { + tools.push(zprint.setup(ZPRINT_VERSION, githubAuth)) + } + if (tools.length === 0) { throw new Error('You must specify at least one clojure tool.') } diff --git a/src/zprint.ts b/src/zprint.ts new file mode 100644 index 0000000..50bb2b8 --- /dev/null +++ b/src/zprint.ts @@ -0,0 +1,69 @@ +import * as core from '@actions/core' +import * as http from '@actions/http-client' +import * as os from 'os' +import * as tc from '@actions/tool-cache' +import {chmod} from 'fs/promises' + +export async function getLatestZprint(githubAuth?: string): Promise { + const client = new http.HttpClient('actions/setup-zprint', undefined, { + allowRetries: true, + maxRetries: 3 + }) + + const res = await client.getJson<{tag_name: string}>( + `https://api.github.com/repos/kkinnear/zprint/releases/latest`, + githubAuth ? {Authorization: githubAuth} : undefined + ) + + const result = res.result?.tag_name?.replace(/^v/, '') + if (result) { + return result + } + + throw new Error(`Can't obtain latest zprint version`) +} + +export function getArtifactName(version: string): string { + const platform = os.platform() + switch (platform) { + case 'win32': + return `zprint-filter-${version}` + case 'darwin': + return `zprintm-${version}` + default: + return `zprintl-${version}` + } +} + +export function getArtifactUrl(version: string): string { + const archiveName = getArtifactName(version) + return `https://github.com/kkinnear/zprint/releases/download/${version}/${archiveName}` +} + +export async function setup( + version: string, + githubAuth?: string +): Promise { + const ver = version === 'latest' ? await getLatestZprint(githubAuth) : version + + let toolDir = tc.find('zprint', ver) + if (!toolDir) { + const archiveUrl = getArtifactUrl(ver) + core.info(`Artifact: ${archiveUrl}`) + + const artifactFile = await tc.downloadTool( + archiveUrl, + undefined, + githubAuth + ) + + await chmod(artifactFile, '0755') + + toolDir = await tc.cacheFile(artifactFile, 'zprint', 'zprint', ver) + core.info(`Saved: ${toolDir}`) + } else { + core.info(`Cached: ${toolDir}`) + } + + core.addPath(toolDir) +}