Skip to content

Commit 3610d4a

Browse files
authored
Merge pull request #86 from weavejester/patch-add-cljfmt
Add cljfmt support
2 parents 8f7bae7 + 7f05c92 commit 3610d4a

File tree

7 files changed

+293
-0
lines changed

7 files changed

+293
-0
lines changed

.github/workflows/smoke-tests.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,32 @@ jobs:
191191
- name: Check clj-kondo version
192192
run: clj-kondo --version
193193

194+
test-cljfmt:
195+
strategy:
196+
matrix:
197+
os: [ubuntu-latest, macOS-latest, windows-latest]
198+
199+
runs-on: ${{ matrix.os }}
200+
201+
steps:
202+
- name: Checkout
203+
uses: actions/checkout@main
204+
205+
- name: Prepare java
206+
uses: actions/setup-java@v3
207+
with:
208+
distribution: 'zulu'
209+
java-version: '8'
210+
211+
- name: Install cljfmt
212+
uses: ./
213+
with:
214+
cljfmt: latest
215+
github-token: ${{ secrets.GITHUB_TOKEN }}
216+
217+
- name: Check cljfmt version
218+
run: cljfmt --version
219+
194220
test-cljstyle:
195221
strategy:
196222
matrix:

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This action sets up Clojure tools environment for using in GitHub Actions.
77
* [boot-clj](https://boot-clj.github.io/)
88
* [babashka](https://babashka.org/)
99
* [clj-kondo](https://github.com/clj-kondo/clj-kondo)
10+
* [cljfmt](https://github.com/weavejester/cljfmt)
1011
* [cljstyle](https://github.com/greglook/cljstyle)
1112
* [deps.clj](https://github.com/borkdude/deps.clj)
1213
* [zprint](https://github.com/kkinnear/zprint)
@@ -55,6 +56,7 @@ jobs:
5556
boot: 2.8.3 # Boot.clj
5657
bb: 0.7.8 # Babashka
5758
clj-kondo: 2022.05.31 # Clj-kondo
59+
cljfmt: 0.10.2 # cljfmt
5860
cljstyle: 0.15.0 # cljstyle
5961
cmd-exe-workaround: 'latest' # Replaces `clojure` with `deps.clj` on Windows
6062
zprint: 1.2.3 # zprint
@@ -89,6 +91,9 @@ jobs:
8991
- name: Get clj-kondo version
9092
run: clj-kondo --version
9193

94+
- name: Get cljfmt version
95+
run: cljfmt --version
96+
9297
- name: Get cljstyle version
9398
# cljstyle is not yet available for windows
9499
if: ${{ matrix.os != 'windows-latest' }}

__tests__/cljfmt.test.ts

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import _os from 'os'
2+
import * as _core from '@actions/core'
3+
import * as _tc from '@actions/tool-cache'
4+
import * as cljfmt from '../src/cljfmt'
5+
6+
const getJson = jest.fn()
7+
jest.mock('@actions/http-client', () => ({
8+
HttpClient: function () {
9+
return {getJson}
10+
}
11+
}))
12+
13+
jest.mock('os')
14+
const os: jest.Mocked<typeof _os> = _os as never
15+
16+
jest.mock('@actions/tool-cache')
17+
const tc: jest.Mocked<typeof _tc> = _tc as never
18+
19+
jest.mock('@actions/core')
20+
const core: jest.Mocked<typeof _core> = _core as never
21+
22+
describe('cljfmt tests', () => {
23+
beforeEach(() => {
24+
jest.resetAllMocks()
25+
})
26+
27+
describe('getLatestCljFmt', () => {
28+
it('uses tag_name as latest version', async () => {
29+
getJson.mockResolvedValueOnce({
30+
result: {tag_name: '1.2.3'}
31+
})
32+
const res = await cljfmt.getLatestCljFmt()
33+
expect(res).toBe('1.2.3')
34+
expect(getJson).toHaveBeenCalledWith(
35+
'https://api.github.com/repos/weavejester/cljfmt/releases/latest',
36+
undefined
37+
)
38+
})
39+
40+
it('supports authorization', async () => {
41+
getJson.mockResolvedValueOnce({
42+
result: {tag_name: '1.2.3'}
43+
})
44+
const res = await cljfmt.getLatestCljFmt('token 123')
45+
expect(res).toBe('1.2.3')
46+
expect(getJson).toHaveBeenCalledWith(
47+
'https://api.github.com/repos/weavejester/cljfmt/releases/latest',
48+
{Authorization: 'token 123'}
49+
)
50+
})
51+
52+
it('throws on http client error', async () => {
53+
getJson.mockRejectedValueOnce(new Error('some error'))
54+
await expect(cljfmt.getLatestCljFmt()).rejects.toThrow('some error')
55+
})
56+
57+
it('throws on wrong client answer', async () => {
58+
getJson.mockResolvedValueOnce({result: {foo: 'bar'}})
59+
await expect(cljfmt.getLatestCljFmt()).rejects.toThrow(
60+
`Can't obtain latest cljfmt version`
61+
)
62+
})
63+
})
64+
65+
describe('getArtifactName', () => {
66+
test.each`
67+
platform | artifact
68+
${'win32'} | ${`cljfmt-1.2.3-win-amd64.zip`}
69+
${'darwin'} | ${`cljfmt-1.2.3-darwin-amd64.tar.gz`}
70+
${'linux'} | ${`cljfmt-1.2.3-linux-amd64.tar.gz`}
71+
${'foobar'} | ${`cljfmt-1.2.3-linux-amd64.tar.gz`}
72+
`('$platform -> $artifact', ({platform, artifact}) => {
73+
os.platform.mockReturnValueOnce(platform as never)
74+
expect(cljfmt.getArtifactName('1.2.3')).toBe(artifact)
75+
})
76+
})
77+
78+
describe('getArtifactUrl', () => {
79+
test.each`
80+
platform | artifact
81+
${'win32'} | ${`cljfmt-1.2.3-win-amd64.zip`}
82+
${'darwin'} | ${`cljfmt-1.2.3-darwin-amd64.tar.gz`}
83+
${'linux'} | ${`cljfmt-1.2.3-linux-amd64.tar.gz`}
84+
${'foobar'} | ${`cljfmt-1.2.3-linux-amd64.tar.gz`}
85+
`('$platform -> $artifact', ({platform, artifact}) => {
86+
os.platform.mockReturnValueOnce(platform as never)
87+
expect(cljfmt.getArtifactUrl('1.2.3')).toBe(
88+
`https://github.com/weavejester/cljfmt/releases/download/1.2.3/${artifact}`
89+
)
90+
})
91+
})
92+
93+
describe('setup', () => {
94+
it('uses cache', async () => {
95+
tc.find.mockReturnValueOnce('/foo/bar')
96+
97+
await cljfmt.setup('1.2.3')
98+
99+
expect(tc.find).toHaveBeenCalledWith('cljfmt', '1.2.3')
100+
expect(core.addPath).toHaveBeenCalledWith('/foo/bar')
101+
})
102+
103+
it('uses cache', async () => {
104+
tc.find.mockReturnValueOnce('/foo/bar')
105+
106+
await cljfmt.setup('1.2.3')
107+
108+
expect(tc.find).toHaveBeenCalledWith('cljfmt', '1.2.3')
109+
expect(core.addPath).toHaveBeenCalledWith('/foo/bar')
110+
})
111+
112+
it('fetches exact version', async () => {
113+
tc.downloadTool.mockResolvedValueOnce('/foo/cljfmt.tar.gz')
114+
tc.extractTar.mockResolvedValueOnce('/bar/baz')
115+
tc.cacheDir.mockResolvedValueOnce('/qux')
116+
117+
await cljfmt.setup('1.2.3', 'token 123')
118+
119+
expect(tc.find).toHaveBeenCalledWith('cljfmt', '1.2.3')
120+
expect(tc.downloadTool).toHaveBeenCalledWith(
121+
'https://github.com/weavejester/cljfmt/releases/download/1.2.3/cljfmt-1.2.3-linux-amd64.tar.gz',
122+
undefined,
123+
'token 123'
124+
)
125+
expect(tc.cacheDir).toHaveBeenCalledWith('/bar/baz', 'cljfmt', '1.2.3')
126+
expect(core.addPath).toHaveBeenCalledWith('/qux')
127+
})
128+
129+
it('fetches latest version', async () => {
130+
getJson.mockResolvedValueOnce({
131+
result: {tag_name: '9.9.9'}
132+
})
133+
tc.downloadTool.mockResolvedValueOnce('/foo/cljfmt.tar.gz')
134+
tc.extractTar.mockResolvedValueOnce('/bar/baz')
135+
tc.cacheDir.mockResolvedValueOnce('/qux')
136+
137+
await cljfmt.setup('latest', 'token 123')
138+
139+
expect(getJson).toHaveBeenCalledWith(
140+
'https://api.github.com/repos/weavejester/cljfmt/releases/latest',
141+
{Authorization: 'token 123'}
142+
)
143+
expect(tc.find).toHaveBeenCalledWith('cljfmt', '9.9.9')
144+
expect(tc.downloadTool).toHaveBeenCalledWith(
145+
'https://github.com/weavejester/cljfmt/releases/download/9.9.9/cljfmt-9.9.9-linux-amd64.tar.gz',
146+
undefined,
147+
'token 123'
148+
)
149+
expect(tc.cacheDir).toHaveBeenCalledWith('/bar/baz', 'cljfmt', '9.9.9')
150+
expect(core.addPath).toHaveBeenCalledWith('/qux')
151+
})
152+
})
153+
})

__tests__/entrypoint.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as _boot from '../src/boot'
44
import * as _cli from '../src/cli'
55
import * as _bb from '../src/babashka'
66
import * as _cljKondo from '../src/clj-kondo'
7+
import * as _cljfmt from '../src/cljfmt'
78
import * as _cljstyle from '../src/cljstyle'
89
import * as _zprint from '../src/zprint'
910
import * as _utils from '../src/utils'
@@ -27,6 +28,9 @@ const bb: jest.Mocked<typeof _bb> = _bb as never
2728
jest.mock('../src/clj-kondo')
2829
const cljKondo: jest.Mocked<typeof _cljKondo> = _cljKondo as never
2930

31+
jest.mock('../src/cljfmt')
32+
const cljfmt: jest.Mocked<typeof _cljfmt> = _cljfmt as never
33+
3034
jest.mock('../src/cljstyle')
3135
const cljstyle: jest.Mocked<typeof _cljstyle> = _cljstyle as never
3236

@@ -98,6 +102,15 @@ describe('setup-clojure', () => {
98102
expect(cljKondo.setup).toHaveBeenCalledWith('1.2.3', 'token abc')
99103
})
100104

105+
it('sets up cljfmt', async () => {
106+
inputs['cljfmt'] = '1.2.3'
107+
inputs['github-token'] = 'abc'
108+
109+
await main()
110+
111+
expect(cljfmt.setup).toHaveBeenCalledWith('1.2.3', 'token abc')
112+
})
113+
101114
it('sets up cljstyle', async () => {
102115
inputs['cljstyle'] = '1.2.3'
103116
inputs['github-token'] = 'abc'

action.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ inputs:
2626
description: 'Babashka version to install, `latest` can be used.'
2727
clj-kondo:
2828
description: 'Clj-kondo version to install, `latest` can be used.'
29+
cljfmt:
30+
description: 'cljfmt version to install, `latest` can be used.'
2931
cljstyle:
3032
description: 'cljstyle version to install, `latest` can be used.'
3133
zprint:

src/cljfmt.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import * as core from '@actions/core'
2+
import * as http from '@actions/http-client'
3+
import * as os from 'os'
4+
import * as tc from '@actions/tool-cache'
5+
6+
export const identifier = 'cljfmt'
7+
8+
export async function getLatestCljFmt(githubAuth?: string): Promise<string> {
9+
const client = new http.HttpClient('actions/setup-cljfmt', undefined, {
10+
allowRetries: true,
11+
maxRetries: 3
12+
})
13+
14+
const res = await client.getJson<{tag_name: string}>(
15+
`https://api.github.com/repos/weavejester/cljfmt/releases/latest`,
16+
githubAuth ? {Authorization: githubAuth} : undefined
17+
)
18+
19+
const result = res.result?.tag_name
20+
if (result) {
21+
return result
22+
}
23+
24+
throw new Error(`Can't obtain latest cljfmt version`)
25+
}
26+
27+
export function getArtifactName(version: string): string {
28+
const platform = os.platform()
29+
switch (platform) {
30+
case 'win32':
31+
return `cljfmt-${version}-win-amd64.zip`
32+
case 'darwin':
33+
return `cljfmt-${version}-darwin-amd64.tar.gz`
34+
default:
35+
return `cljfmt-${version}-linux-amd64.tar.gz`
36+
}
37+
}
38+
39+
export function getArtifactUrl(version: string): string {
40+
const archiveName = getArtifactName(version)
41+
return `https://github.com/weavejester/cljfmt/releases/download/${version}/${archiveName}`
42+
}
43+
44+
export async function extract(source: string): Promise<string> {
45+
return source.endsWith('.zip')
46+
? await tc.extractZip(source)
47+
: await tc.extractTar(source)
48+
}
49+
50+
export async function setup(
51+
version: string,
52+
githubAuth?: string
53+
): Promise<void> {
54+
const ver = version === 'latest' ? await getLatestCljFmt(githubAuth) : version
55+
56+
let toolDir = tc.find(identifier, ver)
57+
if (!toolDir) {
58+
const archiveUrl = getArtifactUrl(ver)
59+
core.info(`Downloading: ${archiveUrl}`)
60+
61+
const artifactFile = await tc.downloadTool(
62+
archiveUrl,
63+
undefined,
64+
githubAuth
65+
)
66+
67+
const extractedDir = await extract(artifactFile)
68+
toolDir = await tc.cacheDir(extractedDir, identifier, ver)
69+
core.info(`Caching directory: ${toolDir}`)
70+
} else {
71+
core.info(`Using cached directory: ${toolDir}`)
72+
}
73+
74+
core.addPath(toolDir)
75+
}

0 commit comments

Comments
 (0)