Add clj-kondo support

This commit is contained in:
Sergei Zharinov 2022-06-02 09:36:11 +03:00
parent 7a3a170982
commit 38353796d2
7 changed files with 279 additions and 6 deletions

View File

@ -150,3 +150,31 @@ jobs:
- name: Check babashka version - name: Check babashka version
run: bb --version run: bb --version
test-clj-kondo:
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@v2
with:
distribution: 'zulu'
java-version: '8'
- name: Install clj-kondo
# uses: DeLaGuardo/setup-clojure@master
uses: ./
with:
clj-kondo: latest
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Check clj-kondo version
run: clj-kondo --version

View File

@ -6,6 +6,7 @@ This action sets up Clojure tools environment for using in GitHub Actions.
* Leiningen * Leiningen
* boot-clj * boot-clj
* Babashka * Babashka
* Clj-kondo
All three major tools available for MacOS and ubuntu based runners, Leiningen and Clojure CLI also available on Windows All three major tools available for MacOS and ubuntu based runners, Leiningen and Clojure CLI also available on Windows
@ -48,6 +49,7 @@ jobs:
lein: 2.9.1 # Leiningen lein: 2.9.1 # Leiningen
boot: 2.8.3 # Boot.clj boot: 2.8.3 # Boot.clj
bb: 0.7.8 # Babashka bb: 0.7.8 # Babashka
clj-kondo: 2022.05.31 # Clj-kondo
# (optional) To avoid rate limit errors please provide github token # (optional) To avoid rate limit errors please provide github token
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}

153
__tests__/clj-kondo.test.ts Normal file
View File

@ -0,0 +1,153 @@
import _os from 'os'
import * as _core from '@actions/core'
import * as _tc from '@actions/tool-cache'
import * as cljKondo from '../src/clj-kondo'
const getJson = jest.fn()
jest.mock('@actions/http-client', () => ({
HttpClient: function () {
return {getJson}
}
}))
jest.mock('os')
const os: jest.Mocked<typeof _os> = _os as never
jest.mock('@actions/tool-cache')
const tc: jest.Mocked<typeof _tc> = _tc as never
jest.mock('@actions/core')
const core: jest.Mocked<typeof _core> = _core as never
describe('tdeps tests', () => {
beforeEach(() => {
jest.resetAllMocks()
})
describe('getLatestCljKondo', () => {
it('uses tag_name as latest version', async () => {
getJson.mockResolvedValueOnce({
result: {tag_name: 'v1.2.3'}
})
const res = await cljKondo.getLatestCljKondo()
expect(res).toBe('1.2.3')
expect(getJson).toHaveBeenCalledWith(
'https://api.github.com/repos/clj-kondo/clj-kondo/releases/latest',
undefined
)
})
it('supports authorization', async () => {
getJson.mockResolvedValueOnce({
result: {tag_name: 'v1.2.3'}
})
const res = await cljKondo.getLatestCljKondo('token 123')
expect(res).toBe('1.2.3')
expect(getJson).toHaveBeenCalledWith(
'https://api.github.com/repos/clj-kondo/clj-kondo/releases/latest',
{Authorization: 'token 123'}
)
})
it('throws on http client error', async () => {
getJson.mockRejectedValueOnce(new Error('some error'))
await expect(cljKondo.getLatestCljKondo()).rejects.toThrow('some error')
})
it('throws on wrong client answer', async () => {
getJson.mockResolvedValueOnce({result: {foo: 'bar'}})
await expect(cljKondo.getLatestCljKondo()).rejects.toThrow(
`Can't obtain latest clj-kondo version`
)
})
})
describe('getArtifactName', () => {
test.each`
platform | artifact
${'win32'} | ${`clj-kondo-1.2.3-windows-amd64.zip`}
${'darwin'} | ${`clj-kondo-1.2.3-macos-amd64.zip`}
${'linux'} | ${`clj-kondo-1.2.3-linux-amd64.zip`}
${'foobar'} | ${`clj-kondo-1.2.3-linux-amd64.zip`}
`('$platform -> $artifact', ({platform, artifact}) => {
os.platform.mockReturnValueOnce(platform as never)
expect(cljKondo.getArtifactName('1.2.3')).toBe(artifact)
})
})
describe('getArtifactUrl', () => {
test.each`
platform | artifact
${'win32'} | ${`clj-kondo-1.2.3-windows-amd64.zip`}
${'darwin'} | ${`clj-kondo-1.2.3-macos-amd64.zip`}
${'linux'} | ${`clj-kondo-1.2.3-linux-amd64.zip`}
${'foobar'} | ${`clj-kondo-1.2.3-linux-amd64.zip`}
`('$platform -> $artifact', ({platform, artifact}) => {
os.platform.mockReturnValueOnce(platform as never)
expect(cljKondo.getArtifactUrl('1.2.3')).toBe(
`https://github.com/clj-kondo/clj-kondo/releases/download/v1.2.3/${artifact}`
)
})
})
describe('setup', () => {
it('uses cache', async () => {
tc.find.mockReturnValueOnce('/foo/bar')
await cljKondo.setup('1.2.3')
expect(tc.find).toHaveBeenCalledWith('clj-kondo', '1.2.3')
expect(core.addPath).toHaveBeenCalledWith('/foo/bar')
})
it('uses cache', async () => {
tc.find.mockReturnValueOnce('/foo/bar')
await cljKondo.setup('1.2.3')
expect(tc.find).toHaveBeenCalledWith('clj-kondo', '1.2.3')
expect(core.addPath).toHaveBeenCalledWith('/foo/bar')
})
it('fetches exact version', async () => {
tc.downloadTool.mockResolvedValueOnce('/foo/cljKondo.tar.gz')
tc.extractZip.mockResolvedValueOnce('/bar/baz')
tc.cacheDir.mockResolvedValueOnce('/qux')
await cljKondo.setup('1.2.3', 'token 123')
expect(tc.find).toHaveBeenCalledWith('clj-kondo', '1.2.3')
expect(tc.downloadTool).toHaveBeenCalledWith(
'https://github.com/clj-kondo/clj-kondo/releases/download/v1.2.3/clj-kondo-1.2.3-linux-amd64.zip',
undefined,
'token 123'
)
expect(tc.cacheDir).toHaveBeenCalledWith('/bar/baz', 'clj-kondo', '1.2.3')
expect(core.addPath).toHaveBeenCalledWith('/qux')
})
it('fetches latest version', async () => {
getJson.mockResolvedValueOnce({
result: {tag_name: 'v9.9.9'}
})
tc.downloadTool.mockResolvedValueOnce('/foo/cljKondo.tar.gz')
tc.extractZip.mockResolvedValueOnce('/bar/baz')
tc.cacheDir.mockResolvedValueOnce('/qux')
await cljKondo.setup('latest', 'token 123')
expect(getJson).toHaveBeenCalledWith(
'https://api.github.com/repos/clj-kondo/clj-kondo/releases/latest',
{Authorization: 'token 123'}
)
expect(tc.find).toHaveBeenCalledWith('clj-kondo', '9.9.9')
expect(tc.downloadTool).toHaveBeenCalledWith(
'https://github.com/clj-kondo/clj-kondo/releases/download/v9.9.9/clj-kondo-9.9.9-linux-amd64.zip',
undefined,
'token 123'
)
expect(tc.cacheDir).toHaveBeenCalledWith('/bar/baz', 'clj-kondo', '9.9.9')
expect(core.addPath).toHaveBeenCalledWith('/qux')
})
})
})

View File

@ -3,6 +3,7 @@ import * as _lein from '../src/leiningen'
import * as _boot from '../src/boot' import * as _boot from '../src/boot'
import * as _cli from '../src/cli' import * as _cli from '../src/cli'
import * as _bb from '../src/babashka' import * as _bb from '../src/babashka'
import * as _cljKondo from '../src/clj-kondo'
import * as _utils from '../src/utils' import * as _utils from '../src/utils'
import {run} from '../src/entrypoint' import {run} from '../src/entrypoint'
@ -21,6 +22,9 @@ const cli: jest.Mocked<typeof _cli> = _cli as never
jest.mock('../src/babashka') jest.mock('../src/babashka')
const bb: jest.Mocked<typeof _bb> = _bb as never const bb: jest.Mocked<typeof _bb> = _bb as never
jest.mock('../src/clj-kondo')
const cljKondo: jest.Mocked<typeof _cljKondo> = _cljKondo as never
jest.mock('../src/utils') jest.mock('../src/utils')
const utils: jest.Mocked<typeof _utils> = _utils as never const utils: jest.Mocked<typeof _utils> = _utils as never
@ -106,6 +110,15 @@ describe('setup-clojure', () => {
expect(bb.setup).toHaveBeenCalledWith('1.2.3', 'token abc') expect(bb.setup).toHaveBeenCalledWith('1.2.3', 'token abc')
}) })
it('sets up clj-kondo', async () => {
inputs['clj-kondo'] = '1.2.3'
inputs['github-token'] = 'abc'
await run()
expect(cljKondo.setup).toHaveBeenCalledWith('1.2.3', 'token abc')
})
it('throws if none of Clojure tools is specified', async () => { it('throws if none of Clojure tools is specified', async () => {
await run() await run()
expect(core.setFailed).toHaveBeenCalledWith( expect(core.setFailed).toHaveBeenCalledWith(

View File

@ -15,7 +15,9 @@ inputs:
cli: cli:
description: 'Clojure CLI version to make available on the path.' description: 'Clojure CLI version to make available on the path.'
bb: bb:
description: 'Babashka version to install, `latest` can be used. ' description: 'Babashka version to install, `latest` can be used.'
clj-kondo:
description: 'Clj-kondo version to install, `latest` can be used.'
github-token: github-token:
description: >+ description: >+
To fix rate limit errors, provide `secrets.GITHUB_TOKEN` value to this field. To fix rate limit errors, provide `secrets.GITHUB_TOKEN` value to this field.

68
src/clj-kondo.ts Normal file
View File

@ -0,0 +1,68 @@
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'
export async function getLatestCljKondo(githubAuth?: string): Promise<string> {
const client = new http.HttpClient('actions/setup-clj-kondo', undefined, {
allowRetries: true,
maxRetries: 3
})
const res = await client.getJson<{tag_name: string}>(
`https://api.github.com/repos/clj-kondo/clj-kondo/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 clj-kondo version`)
}
export function getArtifactName(version: string): string {
const platform = os.platform()
switch (platform) {
case 'win32':
return `clj-kondo-${version}-windows-amd64.zip`
case 'darwin':
return `clj-kondo-${version}-macos-amd64.zip`
default:
return `clj-kondo-${version}-linux-amd64.zip`
}
}
export function getArtifactUrl(version: string): string {
const archiveName = getArtifactName(version)
return `https://github.com/clj-kondo/clj-kondo/releases/download/v${version}/${archiveName}`
}
export async function setup(
version: string,
githubAuth?: string
): Promise<void> {
const ver =
version === 'latest' ? await getLatestCljKondo(githubAuth) : version
let toolDir = tc.find('clj-kondo', ver)
if (!toolDir) {
const archiveUrl = getArtifactUrl(ver)
core.info(`Downloading: ${archiveUrl}`)
const artifactFile = await tc.downloadTool(
archiveUrl,
undefined,
githubAuth
)
const extractedDir = await tc.extractZip(artifactFile)
toolDir = await tc.cacheDir(extractedDir, 'clj-kondo', ver)
core.info(`Caching directory: ${toolDir}`)
} else {
core.info(`Using cached directory: ${toolDir}`)
}
core.addPath(toolDir)
}

View File

@ -3,6 +3,7 @@ import * as lein from './leiningen'
import * as boot from './boot' import * as boot from './boot'
import * as cli from './cli' import * as cli from './cli'
import * as bb from './babashka' import * as bb from './babashka'
import * as cljKondo from './clj-kondo'
import * as utils from './utils' import * as utils from './utils'
export async function run(): Promise<void> { export async function run(): Promise<void> {
@ -12,6 +13,7 @@ export async function run(): Promise<void> {
const TDEPS_VERSION = core.getInput('tools-deps') const TDEPS_VERSION = core.getInput('tools-deps')
const CLI_VERSION = core.getInput('cli') const CLI_VERSION = core.getInput('cli')
const BB_VERSION = core.getInput('bb') const BB_VERSION = core.getInput('bb')
const CLJ_KONDO_VERSION = core.getInput('clj-kondo')
const githubToken = core.getInput('github-token') const githubToken = core.getInput('github-token')
const githubAuth = githubToken ? `token ${githubToken}` : undefined const githubAuth = githubToken ? `token ${githubToken}` : undefined
@ -48,13 +50,18 @@ export async function run(): Promise<void> {
await bb.setup(BB_VERSION, githubAuth) await bb.setup(BB_VERSION, githubAuth)
} }
if (CLJ_KONDO_VERSION) {
await cljKondo.setup(CLJ_KONDO_VERSION, githubAuth)
}
if ( if (
!( !(
BOOT_VERSION || BOOT_VERSION ||
LEIN_VERSION || LEIN_VERSION ||
TDEPS_VERSION || TDEPS_VERSION ||
CLI_VERSION || CLI_VERSION ||
BB_VERSION BB_VERSION ||
CLJ_KONDO_VERSION
) )
) { ) {
throw new Error('You must specify at least one clojure tool.') throw new Error('You must specify at least one clojure tool.')