Add support for version ranges (#9)

* Add support for version ranges

* Fix audit

* Update workflow

* Update dist

* Remove unexpected input

* Add  as step
This commit is contained in:
Imran Ismail
2020-09-25 10:47:06 +08:00
committed by GitHub
parent 2a4b82aea8
commit f54a2cb09e
15 changed files with 13232 additions and 3900 deletions

View File

@@ -1,6 +1,6 @@
{ {
"plugins": ["jest", "@typescript-eslint"], "plugins": ["jest", "@typescript-eslint"],
"extends": ["plugin:github/es6"], "extends": ["plugin:github/recommended"],
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {
"ecmaVersion": 9, "ecmaVersion": 9,
@@ -16,13 +16,11 @@
"@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error", "@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error", "@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-ignore": "error", "@typescript-eslint/ban-ts-comment": "error",
"camelcase": "off", "camelcase": "off",
"@typescript-eslint/camelcase": "error", "@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}], "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
"@typescript-eslint/func-call-spacing": ["error", "never"], "@typescript-eslint/func-call-spacing": ["error", "never"],
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
"@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-explicit-any": "error",
@@ -32,7 +30,6 @@
"@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn", "@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-object-literal-type-assertion": "error",
"@typescript-eslint/no-unnecessary-qualifier": "error", "@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error", "@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error", "@typescript-eslint/no-useless-constructor": "error",
@@ -40,7 +37,6 @@
"@typescript-eslint/prefer-for-of": "warn", "@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn", "@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error", "@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-interface": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error", "@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error", "@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error", "@typescript-eslint/require-array-sort-compare": "error",

9
.github/dependaboy.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
version: 2
updates:
# Enable version updates for npm
- package-ecosystem: 'npm'
# Look for `package.json` and `lock` files in the `root` directory
directory: '/'
# Check the npm registry for updates every day (weekdays)
schedule:
interval: 'daily'

View File

@@ -1,16 +0,0 @@
name: "build-test"
on: # rebuild any PRs and main branch changes
pull_request:
push:
branches:
- master
- 'releases/*'
jobs:
build: # make sure build/ci work properly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: |
npm ci
npm run all

23
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: 'build-test'
on: # rebuild any PRs and main branch changes
pull_request:
push:
branches:
- main
- 'releases/*'
jobs:
build: # make sure build/ci work properly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: |
npm install
- run: |
npm run all
test: # make sure the action works on a clean machine without building
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./
- run: kustomize version

View File

@@ -1,11 +0,0 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}

10
.prettierrc.json Normal file
View File

@@ -0,0 +1,10 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid"
}

1
.tool-versions Normal file
View File

@@ -0,0 +1 @@
nodejs 14.12.0

View File

@@ -4,29 +4,32 @@
# Create a JavaScript Action using TypeScript # Create a JavaScript Action using TypeScript
Use this template to bootstrap the creation of a JavaScript action.:rocket: Use this template to bootstrap the creation of a TypeScript action.:rocket:
This template includes compilication support, tests, a validation workflow, publishing, and versioning guidance. This template includes compilation support, tests, a validation workflow, publishing, and versioning guidance.
If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action) If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action)
## Create an action from this template ## Create an action from this template
Click the `Use this Template` and provide the new repo details for your action Click the `Use this Template` and provide the new repo details for your action
## Code in Master ## Code in Main
Install the dependencies
Install the dependencies
```bash ```bash
$ npm install $ npm install
``` ```
Build the typescript and package it for distribution Build the typescript and package it for distribution
```bash ```bash
$ npm run build && npm run pack $ npm run build && npm run package
``` ```
Run the tests :heavy_check_mark: Run the tests :heavy_check_mark:
```bash ```bash
$ npm test $ npm test
@@ -55,9 +58,9 @@ import * as core from '@actions/core';
... ...
async function run() { async function run() {
try { try {
... ...
} }
catch (error) { catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
} }
@@ -70,23 +73,26 @@ See the [toolkit documentation](https://github.com/actions/toolkit/blob/master/R
## Publish to a distribution branch ## Publish to a distribution branch
Actions are run from GitHub repos so we will checkin the packed dist folder. Actions are run from GitHub repos so we will checkin the packed dist folder.
Then run [ncc](https://github.com/zeit/ncc) and push the results: Then run [ncc](https://github.com/zeit/ncc) and push the results:
```bash ```bash
$ npm run pack $ npm run package
$ git add dist $ git add dist
$ git commit -a -m "prod dependencies" $ git commit -a -m "prod dependencies"
$ git push origin releases/v1 $ git push origin releases/v1
``` ```
Your action is now published! :rocket: Note: We recommend using the `--license` option for ncc, which will create a license file for all of the production node modules used in your project.
Your action is now published! :rocket:
See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
## Validate ## Validate
You can now validate the action by referencing `./` in a workflow in your repo (see [test.yml](.github/workflows/test.yml)]) You can now validate the action by referencing `./` in a workflow in your repo (see [test.yml](.github/workflows/test.yml))
```yaml ```yaml
uses: ./ uses: ./
@@ -94,8 +100,8 @@ with:
milliseconds: 1000 milliseconds: 1000
``` ```
See the [actions tab](https://github.com/actions/javascript-action/actions) for runs of this action! :rocket: See the [actions tab](https://github.com/actions/typescript-action/actions) for runs of this action! :rocket:
## Usage: ## Usage:
After testing you can [create a v1 tag](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) to reference the stable and latest V1 action After testing you can [create a v1 tag](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) to reference the stable and latest V1 action

View File

@@ -10,6 +10,7 @@ process.env['RUNNER_TOOL_CACHE'] = toolDir
process.env['RUNNER_TEMP'] = tempDir process.env['RUNNER_TEMP'] = tempDir
import * as installer from '../src/installer' import * as installer from '../src/installer'
import * as semver from 'semver'
const IS_WINDOWS = os.platform() === 'win32' const IS_WINDOWS = os.platform() === 'win32'
@@ -24,6 +25,10 @@ describe('installer tests', () => {
await io.rmRF(tempDir) await io.rmRF(tempDir)
}, 100000) }, 100000)
it('Acquires the latest kustomize version 3.x successfully', () => {
expect(async () => await installer.getKustomize('3.x')).not.toThrow()
}, 100000)
it('Acquires kustomize version 3.2.0 successfully', async () => { it('Acquires kustomize version 3.2.0 successfully', async () => {
await installer.getKustomize('3.2.0') await installer.getKustomize('3.2.0')
const kustomizeDir = path.join(toolDir, 'kustomize', '3.2.0', os.arch()) const kustomizeDir = path.join(toolDir, 'kustomize', '3.2.0', os.arch())

7029
dist/index.js vendored

File diff suppressed because it is too large Load Diff

1
dist/index.js.map vendored Normal file

File diff suppressed because one or more lines are too long

3906
dist/sourcemap-register.js vendored Normal file

File diff suppressed because it is too large Load Diff

5960
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,9 @@
"format": "prettier --write **/*.ts", "format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts", "format-check": "prettier --check **/*.ts",
"lint": "eslint src/**/*.ts", "lint": "eslint src/**/*.ts",
"pack": "ncc build", "package": "ncc build --source-map",
"test": "jest", "test": "jest",
"all": "npm run build && npm run format && npm run lint && npm run pack && npm test" "all": "npm run build && npm run format && npm run lint && npm run package && npm test"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -25,26 +25,26 @@
"author": "Imran Ismail", "author": "Imran Ismail",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.0", "@actions/core": "^1.2.4",
"@actions/io": "^1.0.2", "@actions/io": "^1.0.2",
"@actions/tool-cache": "^1.3.3", "@actions/tool-cache": "^1.3.3",
"semver": "^7.1.3", "@octokit/rest": "^18.0.6",
"typed-rest-client": "^1.7.2" "semver": "^7.3.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^24.0.23", "@types/jest": "^26.0.5",
"@types/node": "^12.7.12", "@types/node": "^14.0.23",
"@types/semver": "^7.1.0", "@types/semver": "^7.3.4",
"@typescript-eslint/parser": "^2.8.0", "@typescript-eslint/parser": "^2.8.0",
"@zeit/ncc": "^0.20.5", "@zeit/ncc": "^0.20.5",
"eslint": "^5.16.0", "eslint": "^7.5.0",
"eslint-plugin-github": "^2.0.0", "eslint-plugin-github": "^4.0.1",
"eslint-plugin-jest": "^22.21.0", "eslint-plugin-jest": "^23.18.0",
"jest": "^24.9.0", "jest": "^24.9.0",
"jest-circus": "^24.9.0", "jest-circus": "^26.1.0",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"prettier": "^1.19.1", "prettier": "^2.0.5",
"ts-jest": "^24.2.0", "ts-jest": "^24.2.0",
"typescript": "^3.6.4" "typescript": "^3.9.4"
} }
} }

View File

@@ -1,7 +1,7 @@
// Load tempDirectory before it gets wiped by tool-cache // Load tempDirectory before it gets wiped by tool-cache
import {Octokit} from '@octokit/rest'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as tc from '@actions/tool-cache' import * as tc from '@actions/tool-cache'
import * as restm from 'typed-rest-client/RestClient'
import * as os from 'os' import * as os from 'os'
import * as path from 'path' import * as path from 'path'
import * as semver from 'semver' import * as semver from 'semver'
@@ -10,6 +10,8 @@ let tempDirectory = process.env['RUNNER_TEMPDIRECTORY'] || ''
const osPlat: string = os.platform() const osPlat: string = os.platform()
const osArch: string = os.arch() const osArch: string = os.arch()
const octokit = new Octokit()
const versionRegex = /\d+\.?\d*\.?\d*/
if (!tempDirectory) { if (!tempDirectory) {
let baseLocation let baseLocation
@@ -42,15 +44,15 @@ export async function getKustomize(versionSpec: string): Promise<void> {
version = versionSpec version = versionSpec
} else { } else {
// query kustomize for a matching version // query kustomize for a matching version
version = await queryLatestMatch(versionSpec) const match = await queryLatestMatch(versionSpec)
if (!version) {
if (!match) {
throw new Error( throw new Error(
`Unable to find Kustomize version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.` `Unable to find Kustomize version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`
) )
} }
// check cache version = match
toolPath = tc.find('kustomize', version)
} }
if (!toolPath) { if (!toolPath) {
@@ -62,17 +64,7 @@ export async function getKustomize(versionSpec: string): Promise<void> {
core.addPath(toolPath) core.addPath(toolPath)
} }
interface IAsset { async function queryLatestMatch(versionSpec: string): Promise<string | null> {
browser_download_url: string
name: string
}
interface IKustomizeVersion {
name: string
assets: IAsset[]
}
async function queryLatestMatch(versionSpec: string): Promise<string> {
let dataFileName: string let dataFileName: string
switch (osPlat) { switch (osPlat) {
@@ -94,55 +86,32 @@ async function queryLatestMatch(versionSpec: string): Promise<string> {
} }
const versions: string[] = [] const versions: string[] = []
const dataUrl =
'https://api.github.com/repos/kubernetes-sigs/kustomize/releases'
const rest: restm.RestClient = new restm.RestClient('setup-kustomize')
const kustomizeVersions: IKustomizeVersion[] =
(await rest.get<IKustomizeVersion[]>(dataUrl)).result || []
for (const kustomizeVersion of kustomizeVersions) { for await (const response of octokit.paginate.iterator(
if ( octokit.repos.listReleases,
kustomizeVersion.assets.some(asset => asset.name.includes(dataFileName)) {
) { owner: 'kubernetes-sigs',
const version = semver.clean(kustomizeVersion.name) repo: 'kustomize'
}
)) {
for (const release of response.data) {
if (
release.assets.some(
asset =>
asset.name.includes(dataFileName) &&
asset.name.includes('kustomize')
)
) {
const version = (versionRegex.exec(release.name) || []).shift()
if (version != null) { if (version != null) {
versions.push(version) versions.push(version)
}
} }
} }
} }
return evaluateVersions(versions, versionSpec) return semver.maxSatisfying(versions, versionSpec)
}
function evaluateVersions(versions: string[], versionSpec: string): string {
let version = ''
core.debug(`evaluating ${versions.length} versions`)
versions = versions.sort((a, b) => {
if (semver.gt(a, b)) {
return 1
}
return -1
})
for (let i = versions.length - 1; i >= 0; i--) {
const potential: string = versions[i]
const satisfied: boolean = semver.satisfies(potential, versionSpec)
if (satisfied) {
version = potential
break
}
}
if (version) {
core.debug(`matched: ${version}`)
} else {
core.debug('match not found')
}
return version
} }
async function acquireKustomize(version: string): Promise<string> { async function acquireKustomize(version: string): Promise<string> {