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
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
* boot-clj
* Babashka
* Clj-kondo
All three major tools available for MacOS and ubuntu based runners, Leiningen and Clojure CLI also available on Windows
@ -44,10 +45,11 @@ jobs:
# Install just one or all simultaneously
# The value must indicate a particular version of the tool, or use 'latest'
# to always provision the latest version
cli: 1.10.1.693 # Clojure CLI based on tools.deps
lein: 2.9.1 # Leiningen
boot: 2.8.3 # Boot.clj
bb: 0.7.8 # Babashka
cli: 1.10.1.693 # Clojure CLI based on tools.deps
lein: 2.9.1 # Leiningen
boot: 2.8.3 # Boot.clj
bb: 0.7.8 # Babashka
clj-kondo: 2022.05.31 # Clj-kondo
# (optional) To avoid rate limit errors please provide 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 _cli from '../src/cli'
import * as _bb from '../src/babashka'
import * as _cljKondo from '../src/clj-kondo'
import * as _utils from '../src/utils'
import {run} from '../src/entrypoint'
@ -21,6 +22,9 @@ const cli: jest.Mocked<typeof _cli> = _cli as never
jest.mock('../src/babashka')
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')
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')
})
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 () => {
await run()
expect(core.setFailed).toHaveBeenCalledWith(

View File

@ -15,7 +15,9 @@ inputs:
cli:
description: 'Clojure CLI version to make available on the path.'
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:
description: >+
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 cli from './cli'
import * as bb from './babashka'
import * as cljKondo from './clj-kondo'
import * as utils from './utils'
export async function run(): Promise<void> {
@ -12,6 +13,7 @@ export async function run(): Promise<void> {
const TDEPS_VERSION = core.getInput('tools-deps')
const CLI_VERSION = core.getInput('cli')
const BB_VERSION = core.getInput('bb')
const CLJ_KONDO_VERSION = core.getInput('clj-kondo')
const githubToken = core.getInput('github-token')
const githubAuth = githubToken ? `token ${githubToken}` : undefined
@ -48,13 +50,18 @@ export async function run(): Promise<void> {
await bb.setup(BB_VERSION, githubAuth)
}
if (CLJ_KONDO_VERSION) {
await cljKondo.setup(CLJ_KONDO_VERSION, githubAuth)
}
if (
!(
BOOT_VERSION ||
LEIN_VERSION ||
TDEPS_VERSION ||
CLI_VERSION ||
BB_VERSION
BB_VERSION ||
CLJ_KONDO_VERSION
)
) {
throw new Error('You must specify at least one clojure tool.')