Skip to content

Commit 8996503

Browse files
authored
optional input to validate checksum (#20)
1 parent 7c1cc82 commit 8996503

File tree

10 files changed

+140
-14
lines changed

10 files changed

+140
-14
lines changed

.github/workflows/test.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
npm install
1616
- run: |
1717
npm run all
18-
test: # make sure the action works on a clean machine without building
18+
test-latest:
1919
runs-on: ubuntu-latest
2020
steps:
2121
- uses: actions/checkout@v3
@@ -27,9 +27,22 @@ jobs:
2727
uses: ./
2828
- run: |
2929
which rye
30+
test-specific-version:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v3
3034
- name: Install specific version
3135
uses: ./
3236
with:
3337
version: '0.11.0'
3438
- run: |
3539
which rye
40+
test-checksum:
41+
runs-on: ubuntu-latest
42+
steps:
43+
- uses: actions/checkout@v3
44+
- name: Checksum matches expected
45+
uses: ./
46+
with:
47+
version: '0.11.0'
48+
checksum: '00e795573477a2fe2b3c0ac748240364c3369218d314d1df47d2653764e9bfb1'

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ You can also specify a specific version of rye
2727
version: '0.11.0'
2828
```
2929
30+
You can also specify a checksum to validate the downloaded file.
31+
The sha265 hashes can be found on the [releases page](https://github.com/mitsuhiko/rye/releases)
32+
of the rye repo.
33+
34+
```yaml
35+
- name: Install a specific version and validate the checksum
36+
uses: eifinger/setup-rye@v1
37+
with:
38+
version: '0.11.0'
39+
checksum: '00e795573477a2fe2b3c0ac748240364c3369218d314d1df47d2653764e9bfb1'
40+
```
41+
3042
## How it works
3143
3244
This action downloads rye from the releases of the [rye repo](https://github.com/mitsuhiko/rye) and uses the [GitHub Actions Toolkit](https://github.com/actions/toolkit) to cache it as a tool to speed up consecutive runs especially on self-hosted runners.

__tests__/fixtures/checksumfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Random file content

__tests__/utils.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {expect, test} from '@jest/globals'
2+
3+
import * as utils from '../src/utils'
4+
5+
test('checksum should match', async () => {
6+
const validChecksum =
7+
'f3da96ec7e995debee7f5d52ecd034dfb7074309a1da42f76429ecb814d813a3'
8+
const filePath = '__tests__/fixtures/checksumfile'
9+
const isValid = await utils.validateCheckSum(filePath, validChecksum)
10+
expect(isValid).toBeTruthy()
11+
})

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ inputs:
55
version:
66
description: 'The version of rye to install'
77
default: 'latest'
8+
checksum:
9+
description: 'The checksum of the rye version to install'
10+
required: false
811
runs:
912
using: 'node16'
1013
main: 'dist/setup/index.js'

dist/setup/index.js

Lines changed: 62 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/setup/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"lint": "eslint src/**/*.ts",
1212
"package": "ncc build -o dist/setup src/setup-rye.ts --source-map --license licenses.txt",
1313
"test": "jest",
14-
"act": "act -j test --container-architecture linux/amd64 -s GITHUB_TOKEN=\"$(gh auth token)\"",
14+
"act": "act pull_request -W .github/workflows/test.yml --container-architecture linux/amd64 -s GITHUB_TOKEN=\"$(gh auth token)\"",
1515
"all": "npm run build && npm run format && npm run lint && npm run package && npm test"
1616
},
1717
"repository": {

src/setup-rye.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@ import * as io from '@actions/io'
55
import * as octokit from '@octokit/rest'
66
import * as path from 'path'
77
import fetch from 'node-fetch'
8-
import {OWNER, REPO} from './utils'
8+
import {OWNER, REPO, validateCheckSum} from './utils'
99

1010
async function run(): Promise<void> {
1111
const platform = 'linux'
1212
const arch = 'x64'
1313
const versionInput = core.getInput('version')
14+
const checkSum = core.getInput('checksum')
1415

1516
try {
1617
const version = await resolveVersion(versionInput)
1718
let cachedPath = tryGetFromCache(arch, version)
1819
if (cachedPath) {
1920
core.info(`Found Rye in cache for ${version}`)
2021
} else {
21-
cachedPath = await setupRye(platform, arch, version)
22+
cachedPath = await setupRye(platform, arch, version, checkSum)
2223
}
2324
addRyeToPath(cachedPath)
2425
addMatchers()
@@ -65,24 +66,34 @@ function tryGetFromCache(arch: string, version: string): string | undefined {
6566
async function setupRye(
6667
platform: string,
6768
arch: string,
68-
version: string
69+
version: string,
70+
checkSum: string | undefined
6971
): Promise<string> {
70-
const downloadPath = await downloadVersion(platform, arch, version)
72+
const downloadPath = await downloadVersion(platform, arch, version, checkSum)
7173
const cachedPath = await installRye(downloadPath, arch, version)
7274
return cachedPath
7375
}
7476

7577
async function downloadVersion(
7678
platform: string,
7779
arch: string,
78-
version: string
80+
version: string,
81+
checkSum: string | undefined
7982
): Promise<string> {
8083
const binary = `rye-x86_64-${platform}`
8184
const downloadUrl = `https://github.com/mitsuhiko/rye/releases/download/${version}/${binary}.gz`
8285
core.info(`Downloading Rye from "${downloadUrl}" ...`)
8386

8487
try {
8588
const downloadPath = await tc.downloadTool(downloadUrl)
89+
if (checkSum !== undefined && checkSum !== '') {
90+
const isValid = await validateCheckSum(downloadPath, checkSum)
91+
if (!isValid) {
92+
throw new Error(
93+
`Checksum for ${downloadPath} did not match ${checkSum}.`
94+
)
95+
}
96+
}
8697

8798
await extract(downloadPath)
8899
return downloadPath

src/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import * as fs from 'fs'
2+
import * as crypto from 'crypto'
3+
14
export const IS_WINDOWS = process.platform === 'win32'
25
export const IS_LINUX = process.platform === 'linux'
36
export const IS_MAC = process.platform === 'darwin'
@@ -6,3 +9,19 @@ export const WINDOWS_PLATFORMS = ['win32', 'win64']
69

710
export const REPO = 'rye'
811
export const OWNER = 'mitsuhiko'
12+
13+
export async function validateCheckSum(
14+
filePath: string,
15+
expected: string
16+
): Promise<boolean> {
17+
return new Promise((resolve, reject) => {
18+
const hash = crypto.createHash('sha256')
19+
const stream = fs.createReadStream(filePath)
20+
stream.on('error', err => reject(err))
21+
stream.on('data', chunk => hash.update(chunk))
22+
stream.on('end', () => {
23+
const actual = hash.digest('hex')
24+
resolve(actual === expected)
25+
})
26+
})
27+
}

0 commit comments

Comments
 (0)