Compare commits

...

11 Commits

Author SHA1 Message Date
Imran Ismail
430fa071e8 Run jest tests sequentially 2020-09-25 13:06:21 +08:00
Imran Ismail
b0afa08459 Remove unused import 2020-09-25 12:58:37 +08:00
Imran Ismail
9503343f5a Update test.yml 2020-09-25 12:55:49 +08:00
Imran Ismail
51957eba2f Simplify installer logic 2020-09-25 12:53:36 +08:00
Imran Ismail
399ab9d4d6 Fix dependabot config typo 2020-09-25 10:53:18 +08:00
Imran Ismail
f54a2cb09e Add support for version ranges (#9)
* Add support for version ranges

* Fix audit

* Update workflow

* Update dist

* Remove unexpected input

* Add  as step
2020-09-25 10:47:06 +08:00
Imran Ismail
2a4b82aea8 Merge pull request #6 from imranismail/dependabot/npm_and_yarn/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19
2020-09-07 16:21:55 +08:00
dependabot[bot]
fff6152ccc Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-18 04:28:03 +00:00
Imran Ismail
dd60f3d86e Merge pull request #5 from imranismail/dependabot/npm_and_yarn/actions/http-client-1.0.8
Bump @actions/http-client from 1.0.6 to 1.0.8
2020-04-30 02:04:54 +08:00
dependabot[bot]
3f35d588be Bump @actions/http-client from 1.0.6 to 1.0.8
Bumps [@actions/http-client](https://github.com/actions/http-client) from 1.0.6 to 1.0.8.
- [Release notes](https://github.com/actions/http-client/releases)
- [Changelog](https://github.com/actions/http-client/blob/master/RELEASES.md)
- [Commits](https://github.com/actions/http-client/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-04-29 18:03:39 +00:00
Imran Ismail
823fe14c9e Update README.md 2020-03-31 03:04:29 +08:00
16 changed files with 13289 additions and 4086 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/dependabot.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:
- master
- '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

@@ -12,7 +12,7 @@ jobs:
needs: needs:
- publish-image - publish-image
steps: steps:
- uses: imranismail/setup-kustomize@master - uses: imranismail/setup-kustomize@v1
with: with:
kustomize-version: "3.1.0" kustomize-version: "3.1.0"
- run: git clone https://${REPO_TOKEN}@github.com/org/deployment.git . - run: git clone https://${REPO_TOKEN}@github.com/org/deployment.git .

View File

@@ -24,6 +24,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())

7143
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

5972
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 -i",
"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,15 +1,17 @@
// 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 cache from '@actions/tool-cache'
import * as restm from 'typed-rest-client/RestClient'
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'
import * as fs from 'fs' import * as fs from 'fs'
let tempDirectory = process.env['RUNNER_TEMPDIRECTORY'] || '' let tempDirectory = process.env['RUNNER_TEMPDIRECTORY'] || ''
const osPlat: string = os.platform() const octokit = new Octokit()
const osArch: string = os.arch() const versionRegex = /\d+\.?\d*\.?\d*/
const toolName = 'kustomize'
const platform = process.platform
const arch = process.arch === 'x64' ? 'amd64' : process.arch
if (!tempDirectory) { if (!tempDirectory) {
let baseLocation let baseLocation
@@ -27,185 +29,88 @@ if (!tempDirectory) {
} }
export async function getKustomize(versionSpec: string): Promise<void> { export async function getKustomize(versionSpec: string): Promise<void> {
// check cache let toolPath = cache.find('kustomize', versionSpec)
let toolPath: string
toolPath = tc.find('kustomize', versionSpec)
// If not found in cache, download
if (!toolPath) { if (!toolPath) {
let version: string const version = await getMaxSatisfyingVersion(versionSpec)
const c = semver.clean(versionSpec) || '' toolPath = await acquireVersion(version)
// If explicit version
if (semver.valid(c) != null) {
// version to download
version = versionSpec
} else {
// query kustomize for a matching version
version = await queryLatestMatch(versionSpec)
if (!version) {
throw new Error(
`Unable to find Kustomize version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`
)
}
// check cache
toolPath = tc.find('kustomize', version)
}
if (!toolPath) {
// download, extract, cache
toolPath = await acquireKustomize(version)
}
} }
core.addPath(toolPath) return core.addPath(toolPath)
} }
interface IAsset { interface Version {
browser_download_url: string
name: string name: string
url: string
} }
interface IKustomizeVersion { async function getMaxSatisfyingVersion(versionSpec: string): Promise<Version> {
name: string const versionRange = semver.validRange(versionSpec)
assets: IAsset[] const downloadUrls: Map<string, string> = new Map()
}
async function queryLatestMatch(versionSpec: string): Promise<string> {
let dataFileName: string
switch (osPlat) {
case 'linux':
case 'darwin':
case 'win32':
dataFileName = osPlat
break
default:
throw new Error(`Unexpected OS '${osPlat}'`)
}
switch (osArch) {
case 'x64':
dataFileName = `${dataFileName}_amd64`
break
default:
dataFileName = `${dataFileName}_${osArch}`
}
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) {
const matchingAsset = release.assets.find(
asset =>
asset.name.includes('kustomize') &&
asset.name.includes(platform) &&
asset.name.includes(arch)
)
if (version != null) { if (matchingAsset) {
versions.push(version) const version = (versionRegex.exec(release.name) || []).shift()
if (version != null) {
downloadUrls.set(version, matchingAsset.browser_download_url)
versions.push(version)
}
} }
} }
} }
return evaluateVersions(versions, versionSpec) const versionToDownload = semver.maxSatisfying(versions, versionRange)
}
function evaluateVersions(versions: string[], versionSpec: string): string { if (!versionToDownload) {
let version = '' throw new Error(
`Unable to find Kustomize version '${versionSpec}' for platform '${platform}' and architecture ${arch}.`
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) { const downloadUrl = downloadUrls.get(versionToDownload) as string
core.debug(`matched: ${version}`)
} else {
core.debug('match not found')
}
return version return {name: versionToDownload, url: downloadUrl}
} }
async function acquireKustomize(version: string): Promise<string> { async function acquireVersion(version: Version): Promise<string> {
version = semver.clean(version) || '' const toolFilename =
process.platform === 'win32' ? `${toolName}.exe` : toolName
let downloadUrl: string
let toolPath: string let toolPath: string
let toolFilename = 'kustomize'
const toolName = 'kustomize'
if (osPlat === 'win32') {
toolFilename = `${toolFilename}.exe`
}
if (semver.gte(version, '3.3.0')) {
downloadUrl = `https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v${version}/kustomize_v${version}_%{os}_%{arch}.tar.gz`
} else if (semver.gte(version, '3.2.1')) {
downloadUrl = `https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v${version}/kustomize_kustomize.v${version}_%{os}_%{arch}`
} else {
downloadUrl = `https://github.com/kubernetes-sigs/kustomize/releases/download/v${version}/kustomize_${version}_%{os}_%{arch}`
}
switch (osPlat) {
case 'win32':
if (semver.lte(version, '3.2.1'))
throw new Error(`Unexpected OS '${osPlat}'`)
downloadUrl = downloadUrl.replace('%{os}', 'windows')
if (semver.lt(version, '3.3.0')) downloadUrl = `${downloadUrl}.exe`
break
case 'linux':
case 'darwin':
downloadUrl = downloadUrl.replace('%{os}', osPlat)
break
default:
throw new Error(`Unexpected OS '${osPlat}'`)
}
switch (osArch) {
case 'x64':
downloadUrl = downloadUrl.replace('%{arch}', 'amd64')
break
default:
throw new Error(`Unexpected Arch '${osArch}'`)
}
try { try {
toolPath = await tc.downloadTool(downloadUrl) toolPath = await cache.downloadTool(version.url)
} catch (err) { } catch (err) {
core.debug(err) core.debug(err)
throw new Error(`Failed to download version ${version}: ${err}`) throw new Error(`Failed to download version ${version.name}: ${err}`)
} }
if (downloadUrl.endsWith('.tar.gz')) { if (version.url.endsWith('.tar.gz')) {
toolPath = await tc.extractTar(toolPath) toolPath = await cache.extractTar(toolPath)
toolPath = path.join(toolPath, toolFilename) toolPath = path.join(toolPath, toolFilename)
} }
switch (osPlat) { switch (process.platform) {
case 'linux': case 'linux':
case 'darwin': case 'darwin':
fs.chmodSync(toolPath, 0o755) fs.chmodSync(toolPath, 0o755)
break break
} }
return await tc.cacheFile(toolPath, toolFilename, toolName, version) return await cache.cacheFile(toolPath, toolFilename, toolName, version.name)
} }