This commit is contained in:
Vidya Reddy 2022-06-28 11:39:10 -07:00 коммит произвёл GitHub
Родитель efb25e19ed
Коммит 83c5bf7343
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
34 изменённых файлов: 9628 добавлений и 9066 удалений

Просмотреть файл

@ -4,7 +4,4 @@ about: Create a report to help us improve
title: ''
labels: need-to-triage
assignees: ''
---

48
.github/workflows/defaultLabels.yml поставляемый
Просмотреть файл

@ -1,30 +1,30 @@
name: setting-default-labels
on:
schedule:
- cron: "0 0/3 * * *"
schedule:
- cron: '0 0/3 * * *'
jobs:
label-issues:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
name: Setting issue as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
stale-issue-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
exempt-issue-labels: 'backlog'
label-issues:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
name: Setting issue as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
stale-issue-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
exempt-issue-labels: 'backlog'
- uses: actions/stale@v3
name: Setting PR as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
stale-pr-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
- uses: actions/stale@v3
name: Setting PR as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
stale-pr-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100

110
.github/workflows/integration-tests.yaml поставляемый
Просмотреть файл

@ -1,68 +1,68 @@
name: Integration test for k8s-bake-v1
on:
pull_request:
pull_request:
jobs:
run-integration-test:
name: Validate release and main branch
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2.3.4
name: Checkout branch
run-integration-test:
name: Validate release and main branch
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2.3.4
name: Checkout branch
- name: Install npm packages
run: |
npm install --no-bin-links
- name: Install npm packages
run: |
npm install --no-bin-links
- name: Install ncc
run: npm i -g @vercel/ncc
- name: Install ncc
run: npm i -g @vercel/ncc
- name: Build
run: ncc build src/run.ts -o lib
- name: Build
run: ncc build src/run.ts -o lib
- name: Bake using Helm on ${{ matrix.os }}
uses: ./
with:
renderEngine: "helm"
helmChart: "./testResources/Helm/HelmCharts"
helm-version: "latest"
silent: "false"
namespace: "namespaceExample"
overrideFiles: "./testResources/Helm/values.yaml"
overrides: |
serviceName:aks-helloworld-test
id: helm-bake
- name: Bake using Helm on ${{ matrix.os }}
uses: ./
with:
renderEngine: 'helm'
helmChart: './testResources/Helm/HelmCharts'
helm-version: 'latest'
silent: 'false'
namespace: 'namespaceExample'
overrideFiles: './testResources/Helm/values.yaml'
overrides: |
serviceName:aks-helloworld-test
id: helm-bake
- name: Validate created manifest ${{ matrix.os }}
uses: Azure/k8s-lint@v1
with:
manifests: ${{ steps.helm-bake.outputs.manifestsBundle }}
- name: Validate created manifest ${{ matrix.os }}
uses: Azure/k8s-lint@v1
with:
manifests: ${{ steps.helm-bake.outputs.manifestsBundle }}
- name: Executing latest changes on ${{ matrix.os }}
uses: ./
with:
renderEngine: "kompose"
dockerComposeFile: "./testResources/Kompose/docker-compose.yml"
kompose-version: "latest"
id: kompose-bake
- name: Executing latest changes on ${{ matrix.os }}
uses: ./
with:
renderEngine: 'kompose'
dockerComposeFile: './testResources/Kompose/docker-compose.yml'
kompose-version: 'latest'
id: kompose-bake
- name: validate created manifest ${{ matrix.os }}
uses: Azure/k8s-lint@v1
with:
manifests: ${{ steps.kompose-bake.outputs.manifestsBundle }}
- name: validate created manifest ${{ matrix.os }}
uses: Azure/k8s-lint@v1
with:
manifests: ${{ steps.kompose-bake.outputs.manifestsBundle }}
- name: Bake using Kustomize on ${{ matrix.os }}
uses: ./
with:
renderEngine: "kustomize"
kustomizationPath: "./testResources/Kustomize"
kubectl-version: "latest"
id: kustomize-bake
- name: Bake using Kustomize on ${{ matrix.os }}
uses: ./
with:
renderEngine: 'kustomize'
kustomizationPath: './testResources/Kustomize'
kubectl-version: 'latest'
id: kustomize-bake
- name: Validate created manifest ${{ matrix.os }}
uses: Azure/k8s-lint@v1
with:
manifests: ${{ steps.kustomize-bake.outputs.manifestsBundle }}
- name: Validate created manifest ${{ matrix.os }}
uses: Azure/k8s-lint@v1
with:
manifests: ${{ steps.kustomize-bake.outputs.manifestsBundle }}

18
.github/workflows/prettify-code.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,18 @@
name: 'Run prettify'
on:
pull_request:
push:
branches: [main]
jobs:
prettier:
name: Prettier Check
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Enforce Prettier
uses: actionsx/prettier@v2
with:
args: --check .

18
.github/workflows/release-pr.yml поставляемый
Просмотреть файл

@ -1,14 +1,14 @@
name: Create release PR
on:
workflow_dispatch:
inputs:
release:
description: "Define release version (ex: v1, v2, v3)"
required: true
workflow_dispatch:
inputs:
release:
description: 'Define release version (ex: v1, v2, v3)'
required: true
jobs:
release-pr:
uses: OliverMKing/javascript-release-workflow/.github/workflows/release-pr.yml@main
with:
release: ${{ github.event.inputs.release }}
release-pr:
uses: OliverMKing/javascript-release-workflow/.github/workflows/release-pr.yml@main
with:
release: ${{ github.event.inputs.release }}

10
.github/workflows/tag-and-draft.yml поставляемый
Просмотреть файл

@ -1,10 +1,10 @@
name: Tag and create release draft
on:
push:
branches:
- releases/*
push:
branches:
- releases/*
jobs:
tag-and-release:
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@main
tag-and-release:
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@main

38
.github/workflows/unit-tests.yml поставляемый
Просмотреть файл

@ -1,22 +1,22 @@
name: "Run unit tests."
name: 'Run unit tests.'
on: # rebuild any PRs and main branch changes
pull_request:
branches:
- main
- "releases/*"
push:
branches:
- main
- "releases/*"
pull_request:
branches:
- main
- 'releases/*'
push:
branches:
- main
- 'releases/*'
jobs:
build: # make sure build/ci works properly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Running L0 tests.
run: |
sudo npm install n
sudo n latest
npm install
npm test
build: # make sure build/ci works properly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Running L0 tests.
run: |
sudo npm install n
sudo n latest
npm install
npm test

4
.prettierignore Normal file
Просмотреть файл

@ -0,0 +1,4 @@
# dependencies
/node_modules
coverage
/lib

8
.prettierrc.json Normal file
Просмотреть файл

@ -0,0 +1,8 @@
{
"trailingComma": "none",
"bracketSpacing": false,
"semi": false,
"tabWidth": 3,
"singleQuote": true,
"printWidth": 80
}

Просмотреть файл

@ -4,6 +4,6 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns

Просмотреть файл

@ -1,6 +1,6 @@
# Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

Просмотреть файл

@ -28,9 +28,9 @@ Sets output variable 'manifestsBundle' which contains the location of the manife
```yaml
- uses: azure/k8s-bake@v2.2
with:
renderEngine: "kompose"
dockerComposeFile: "./docker-compose.yml"
kompose-version: "latest"
renderEngine: 'kompose'
dockerComposeFile: './docker-compose.yml'
kompose-version: 'latest'
```
#### Bake using Kubernetes Kustomize
@ -38,12 +38,12 @@ Sets output variable 'manifestsBundle' which contains the location of the manife
```yaml
- uses: azure/k8s-bake@v2.2
with:
renderEngine: "kustomize"
kustomizationPath: "./kustomizeexample/"
arguments: |
--ca-file
./ca-file/
kubectl-version: "latest"
renderEngine: 'kustomize'
kustomizationPath: './kustomizeexample/'
arguments: |
--ca-file
./ca-file/
kubectl-version: 'latest'
```
Refer to the [action metadata file](https://github.com/Azure/k8s-bake/blob/master/action.yml) for details about all the inputs.
@ -54,49 +54,49 @@ Refer to the [action metadata file](https://github.com/Azure/k8s-bake/blob/maste
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: Azure/docker-login@v1
with:
login-server: contoso.azurecr.io
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- uses: Azure/docker-login@v1
with:
login-server: contoso.azurecr.io
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- run: |
docker build . -t contoso.azurecr.io/k8sdemo:${{ github.sha }}
docker push contoso.azurecr.io/k8sdemo:${{ github.sha }}
- run: |
docker build . -t contoso.azurecr.io/k8sdemo:${{ github.sha }}
docker push contoso.azurecr.io/k8sdemo:${{ github.sha }}
- uses: Azure/k8s-set-context@v1
with:
kubeconfig: ${{ secrets.KUBE_CONFIG }}
- uses: Azure/k8s-set-context@v1
with:
kubeconfig: ${{ secrets.KUBE_CONFIG }}
- uses: Azure/k8s-create-secret@v1
with:
container-registry-url: contoso.azurecr.io
container-registry-username: ${{ secrets.REGISTRY_USERNAME }}
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
secret-name: demo-k8s-secret
- uses: Azure/k8s-create-secret@v1
with:
container-registry-url: contoso.azurecr.io
container-registry-username: ${{ secrets.REGISTRY_USERNAME }}
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
secret-name: demo-k8s-secret
- uses: azure/k8s-bake@v2.2
with:
renderEngine: "helm"
helmChart: "./aks-helloworld/"
overrideFiles: "./aks-helloworld/values-override.yaml"
overrides: |
replicas:2
helm-version: "latest"
id: bake
- uses: azure/k8s-bake@v2.2
with:
renderEngine: 'helm'
helmChart: './aks-helloworld/'
overrideFiles: './aks-helloworld/values-override.yaml'
overrides: |
replicas:2
helm-version: 'latest'
id: bake
- uses: Azure/k8s-deploy@v1
with:
manifests: ${{ steps.bake.outputs.manifestsBundle }}
images: |
demo.azurecr.io/k8sdemo:${{ github.sha }}
imagepullsecrets: |
demo-k8s-secret
- uses: Azure/k8s-deploy@v1
with:
manifests: ${{ steps.bake.outputs.manifestsBundle }}
images: |
demo.azurecr.io/k8sdemo:${{ github.sha }}
imagepullsecrets: |
demo-k8s-secret
```
# Contributing

Просмотреть файл

@ -4,7 +4,7 @@
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](<https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)>) of a security vulnerability, please report it to us as described below.
## Reporting Security Issues
@ -12,19 +12,19 @@ If you believe you have found a security vulnerability in any Microsoft-owned re
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.

Просмотреть файл

@ -1,49 +1,50 @@
name: "Kubernetes bake"
description: "Use this action to bake manifest file to be used for deployments using helm, kustomize or kompose"
name: 'Kubernetes bake'
description: 'Use this action to bake manifest file to be used for deployments using helm, kustomize or kompose'
inputs:
renderEngine:
description: "Acceptable values: helm or kompose or kustomize"
required: true
helmChart:
description: "Required if renderEngine == helm. Helm chart to bake."
required: false
namespace:
description: "Relevant if renderEngine == helm. Namespace to be used for Helm option."
arguments:
description: "Acceptable values: helm or kustomize. Arguments to be passed to the Helm or kustomize template command"
required: false
overrideFiles:
description: "Relevant if renderEngine == helm. Array of path to override files. Each path should be mentioned on a newline"
required: false
overrides:
description: "Relevant if renderEngine == helm. Override values to set."
required: false
releaseName:
description: "Relevant if renderEngine == helm. Release name to be used for Helm option."
required: false
kustomizationPath:
description: "Required if renderEngine == kustomization. Path to directory or the Git repository containing kustomization.yaml file."
required: false
dockerComposeFile:
description: "Required if renderEngine == kompose. Path(s) to Docker compose files"
required: false
helm-version:
description: "Version of kubectl. Installs a specific version of helm binary"
required: false
kubectl-version:
description: "Version of kubectl. Installs a specific version of kubectl binary"
required: false
kompose-version:
description: "Version of kubectl. Installs a specific version of kompose binary"
required: false
silent:
description: "When set to true, the output of the bake command would not be shown."
required: false
renderEngine:
description: 'Acceptable values: helm or kompose or kustomize'
required: true
helmChart:
description: 'Required if renderEngine == helm. Helm chart to bake.'
required: false
namespace:
description: 'Relevant if renderEngine == helm. Namespace to be used for Helm option.'
arguments:
description: 'Acceptable values: helm or kustomize. Arguments to be passed to the Helm or kustomize template command'
required: false
overrideFiles:
description: 'Relevant if renderEngine == helm. Array of path to override files. Each path should be mentioned on a newline'
required: false
overrides:
description: 'Relevant if renderEngine == helm. Override values to set.'
required: false
releaseName:
description: 'Relevant if renderEngine == helm. Release name to be used for Helm option.'
required: false
kustomizationPath:
description: 'Required if renderEngine == kustomization. Path to directory or the Git repository containing kustomization.yaml file.'
required: false
dockerComposeFile:
description: 'Required if renderEngine == kompose. Path(s) to Docker compose files'
required: false
helm-version:
description: 'Version of kubectl. Installs a specific version of helm binary'
required: false
kubectl-version:
description: 'Version of kubectl. Installs a specific version of kubectl binary'
required: false
kompose-version:
description: 'Version of kubectl. Installs a specific version of kompose binary'
required: false
silent:
description: 'When set to true, the output of the bake command would not be shown.'
required: false
outputs:
manifestsBundle:
description: "The location of the manifest bundles created by bake action"
manifestsBundle:
description: 'The location of the manifest bundles created by bake action'
branding:
color: "green" # optional, decorates the entry in the GitHub Marketplace
color: 'green' # optional, decorates the entry in the GitHub Marketplace
runs:
using: "node16"
main: "lib/index.js"
using: 'node16'
main: 'lib/index.js'

Просмотреть файл

@ -1,18 +1,18 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true,
coverageThreshold: {
"global": {
"branches": 0,
"functions": 14,
"lines": 27,
"statements": 27
}
}
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true,
coverageThreshold: {
global: {
branches: 0,
functions: 14,
lines: 27,
statements: 27
}
}
}

14622
package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,26 +1,29 @@
{
"name": "k8sbake",
"version": "1.0.0",
"description": "Kubernetes Bake",
"author": "Anumita Shenoy",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.6.0",
"@actions/exec": "^1.1.0",
"@actions/io": "^1.1.1",
"@actions/tool-cache": "^1.7.1"
},
"main": "lib/run.js",
"scripts": {
"build": "tsc",
"test": "jest",
"test-coverage": "jest --coverage"
},
"devDependencies": {
"@types/jest": "^27.0.2",
"@types/node": "^16.11.7",
"jest": "^27.3.1",
"ts-jest": "^27.0.7",
"typescript": "^4.4.4"
}
"name": "k8sbake",
"version": "1.0.0",
"description": "Kubernetes Bake",
"author": "Anumita Shenoy",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.6.0",
"@actions/exec": "^1.1.0",
"@actions/io": "^1.1.1",
"@actions/tool-cache": "^1.7.1"
},
"main": "lib/run.js",
"scripts": {
"build": "tsc",
"test": "jest",
"test-coverage": "jest --coverage",
"format": "prettier --write .",
"format-check": "prettier --check ."
},
"devDependencies": {
"@types/jest": "^27.0.2",
"@types/node": "^16.11.7",
"jest": "^27.3.1",
"prettier": "2.7.1",
"ts-jest": "^27.0.7",
"typescript": "^4.4.4"
}
}

Просмотреть файл

@ -1,222 +1,316 @@
import * as helmUtil from './helm-util';
import * as os from 'os';
import * as fs from 'fs';
import * as path from 'path';
import * as toolCache from '@actions/tool-cache';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as utils from './utilities';
import * as helmUtil from './helm-util'
import * as os from 'os'
import * as fs from 'fs'
import * as path from 'path'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import * as io from '@actions/io'
import * as utils from './utilities'
describe('Testing all funcitons in helm-util file.', () => {
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder')
return [
'file1' as unknown as fs.Dirent,
'file2' as unknown as fs.Dirent,
'folder1' as unknown as fs.Dirent,
'folder2' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder1'))
return [
'file11' as unknown as fs.Dirent,
'file12' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder2'))
return [
'file21' as unknown as fs.Dirent,
'file22' as unknown as fs.Dirent
]
})
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
return {isDirectory: () => isDirectory} as fs.Stats
})
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') return ['file1' as unknown as fs.Dirent, 'file2' as unknown as fs.Dirent, 'folder1' as unknown as fs.Dirent, 'folder2' as unknown as fs.Dirent];
if (file == path.join('mainFolder', 'folder1')) return ['file11' as unknown as fs.Dirent, 'file12' as unknown as fs.Dirent];
if (file == path.join('mainFolder', 'folder2')) return ['file21' as unknown as fs.Dirent, 'file22' as unknown as fs.Dirent];
});
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).toLowerCase().indexOf('file') == -1 ? true: false
return { isDirectory: () => isDirectory } as fs.Stats;
});
expect(helmUtil.walkSync('mainFolder', undefined, 'file21')).toEqual([
path.join('mainFolder', 'folder2', 'file21')
])
expect(fs.readdirSync).toBeCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8)
})
expect(helmUtil.walkSync('mainFolder', undefined, 'file21')).toEqual([path.join('mainFolder', 'folder2', 'file21')]);
expect(fs.readdirSync).toBeCalledTimes(3);
expect(fs.statSync).toBeCalledTimes(8);
});
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder')
return [
'file1' as unknown as fs.Dirent,
'file2' as unknown as fs.Dirent,
'folder1' as unknown as fs.Dirent,
'folder2' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder1'))
return [
'file11' as unknown as fs.Dirent,
'file12' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder2'))
return [
'file21' as unknown as fs.Dirent,
'file22' as unknown as fs.Dirent
]
})
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
return {isDirectory: () => isDirectory} as fs.Stats
})
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') return ['file1' as unknown as fs.Dirent, 'file2' as unknown as fs.Dirent, 'folder1' as unknown as fs.Dirent, 'folder2' as unknown as fs.Dirent];
if (file == path.join('mainFolder', 'folder1')) return ['file11' as unknown as fs.Dirent, 'file12' as unknown as fs.Dirent];
if (file == path.join('mainFolder', 'folder2')) return ['file21' as unknown as fs.Dirent, 'file22' as unknown as fs.Dirent];
});
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).toLowerCase().indexOf('file') == -1 ? true: false
return { isDirectory: () => isDirectory } as fs.Stats;
});
expect(helmUtil.walkSync('mainFolder', undefined, 'helm.exe')).toEqual([])
expect(fs.readdirSync).toBeCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8)
})
expect(helmUtil.walkSync('mainFolder', undefined, 'helm.exe')).toEqual([]);
expect(fs.readdirSync).toBeCalledTimes(3);
expect(fs.statSync).toBeCalledTimes(8);
});
test('downloadHelm() - throw error when unable to download', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
throw 'Unable to download.'
})
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(core, 'debug').mockImplementation()
test('downloadHelm() - throw error when unable to download', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Unable to download.'});
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(core, 'debug').mockImplementation();
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow(
'Failed to download the helm from https://get.helm.sh/helm-v2.14.1-windows-amd64.zip. Error: Unable to download.'
)
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
expect(toolCache.downloadTool).toBeCalledWith(
'https://get.helm.sh/helm-v2.14.1-windows-amd64.zip'
)
})
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow('Failed to download the helm from https://get.helm.sh/helm-v2.14.1-windows-amd64.zip. Error: Unable to download.');
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v2.14.1-windows-amd64.zip');
});
test('downloadHelm() - find helm executable in toolCache and return path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation()
test('downloadHelm() - find helm executable in toolCache and return path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
jest.spyOn(core, 'debug').mockImplementation();
expect(await helmUtil.downloadHelm('v2.14.1')).toBe(
path.join('pathToCachedDir', 'helm.exe')
)
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedDir', 'helm.exe'),
'777'
)
})
expect(await helmUtil.downloadHelm('v2.14.1')).toBe(path.join('pathToCachedDir', 'helm.exe'));
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedDir', 'helm.exe'), '777');
});
test('downloadHelm() - throw error if helm executable not found in cache', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest
.spyOn(toolCache, 'extractZip')
.mockResolvedValue('pathToUnzippedHelm')
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => [])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
test('downloadHelm() - throw error if helm executable not found in cache', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => []);
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow(
'Helm executable not found in path pathToCachedDir'
)
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
expect(toolCache.downloadTool).toBeCalledWith(
'https://get.helm.sh/helm-v2.14.1-windows-amd64.zip'
)
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
})
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow('Helm executable not found in path pathToCachedDir');
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v2.14.1-windows-amd64.zip');
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777');
expect(toolCache.extractZip).toBeCalledWith('pathToTool');
});
test('downloadHelm() - get stable version of helm, download and return path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
const response = JSON.stringify({
tag_name: 'v4.0.0'
})
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest
.spyOn(toolCache, 'extractZip')
.mockResolvedValue('pathToUnzippedHelm')
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
test('downloadHelm() - get stable version of helm, download and return path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
const response = JSON.stringify({
'tag_name': 'v4.0.0'
});
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
expect(await helmUtil.downloadHelm(null)).toBe(
path.join('pathToCachedDir', 'helm.exe')
)
expect(toolCache.find).toBeCalledWith('helm', 'v4.0.0')
expect(toolCache.downloadTool).toBeCalledWith(
'https://get.helm.sh/helm-v4.0.0-windows-amd64.zip'
)
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedDir', 'helm.exe'),
'777'
)
})
expect(await helmUtil.downloadHelm(null)).toBe(path.join('pathToCachedDir', 'helm.exe'));
expect(toolCache.find).toBeCalledWith('helm', 'v4.0.0');
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v4.0.0-windows-amd64.zip');
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777');
expect(toolCache.extractZip).toBeCalledWith('pathToTool');
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedDir', 'helm.exe'), '777');
});
test('installHelm() - download specified version helm and return its path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
throw 'Unable to download'
})
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation()
test('installHelm() - download specified version helm and return its path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir');
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Unable to download'});
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
jest.spyOn(core, 'debug').mockImplementation();
expect(await helmUtil.installHelm('v2.14.1')).toBe(
path.join('pathToCachedDir', 'helm.exe')
)
})
expect(await helmUtil.installHelm('v2.14.1')).toBe(path.join('pathToCachedDir', 'helm.exe'));
});
test('installHelm() - get latest version of helm and return its path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
const response = JSON.stringify({
tag_name: 'v4.0.0'
})
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest
.spyOn(toolCache, 'extractZip')
.mockResolvedValue('pathToUnzippedHelm')
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
jest.spyOn(core, 'debug').mockImplementation()
test('installHelm() - get latest version of helm and return its path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
const response = JSON.stringify({
'tag_name': 'v4.0.0'
});
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
jest.spyOn(core, 'debug').mockImplementation();
expect(await helmUtil.installHelm('latest')).toBe(
path.join('pathToCachedDir', 'helm.exe')
)
})
expect(await helmUtil.installHelm('latest')).toBe(path.join('pathToCachedDir', 'helm.exe'));
});
test('getHelmPath() - download helm and return its path', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1')
jest
.spyOn(toolCache, 'find')
.mockReturnValueOnce('')
.mockReturnValueOnce('pathToCachedDir')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
jest.spyOn(fs, 'chmodSync').mockImplementation()
test('getHelmPath() - download helm and return its path', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1');
jest.spyOn(toolCache, 'find').mockReturnValueOnce('').mockReturnValueOnce('pathToCachedDir');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
jest.spyOn(fs, 'chmodSync').mockImplementation();
expect(await helmUtil.getHelmPath()).toBe(
path.join('pathToCachedDir', 'helm.exe')
)
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
})
expect(await helmUtil.getHelmPath()).toBe(path.join('pathToCachedDir', 'helm.exe'));
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
});
test('getHelmPath() - return helm From toolCache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1')
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool')
test('getHelmPath() - return helm From toolCache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1');
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool');
expect(await helmUtil.getHelmPath()).toBe('pathToTool')
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
})
expect(await helmUtil.getHelmPath()).toBe('pathToTool');
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
});
test('getHelmPath() - return path any version helm executable if version input not specified', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('pathToHelm')
test('getHelmPath() - return path any version helm executable if version input not specified', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('pathToHelm');
expect(await helmUtil.getHelmPath()).toBe('pathToHelm')
expect(core.getInput).toBeCalledWith('helm-version', {required: false})
expect(io.which).toBeCalledWith('helm', false)
})
expect(await helmUtil.getHelmPath()).toBe('pathToHelm');
expect(core.getInput).toBeCalledWith('helm-version', {"required": false});
expect(io.which).toBeCalledWith('helm', false);
});
test('getHelmPath() - return path to any version helm from tool cache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('')
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['pathToHelm'])
test('getHelmPath() - return path to any version helm from tool cache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('');
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['pathToHelm']);
expect(await helmUtil.getHelmPath()).toBe(
path.join('pathToTool', 'helm.exe')
)
expect(toolCache.findAllVersions).toBeCalledWith('helm')
expect(core.getInput).toBeCalledWith('helm-version', {required: false})
expect(io.which).toBeCalledWith('helm', false)
})
expect(await helmUtil.getHelmPath()).toBe(path.join('pathToTool', 'helm.exe'));
expect(toolCache.findAllVersions).toBeCalledWith('helm');
expect(core.getInput).toBeCalledWith('helm-version', {"required": false});
expect(io.which).toBeCalledWith('helm', false);
});
test('installHelm() - throw error when version input not specified and no executable found', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('')
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([])
test('installHelm() - throw error when version input not specified and no executable found', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('');
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([]);
await expect(helmUtil.getHelmPath()).rejects.toThrow(
'helm is not installed, either add setup-helm action or provide "helm-version" input to download helm'
)
expect(toolCache.findAllVersions).toBeCalledWith('helm')
expect(core.getInput).toBeCalledWith('helm-version', {required: false})
expect(io.which).toBeCalledWith('helm', false)
})
await expect(helmUtil.getHelmPath()).rejects.toThrow('helm is not installed, either add setup-helm action or provide "helm-version" input to download helm');
expect(toolCache.findAllVersions).toBeCalledWith('helm');
expect(core.getInput).toBeCalledWith('helm-version', {"required": false});
expect(io.which).toBeCalledWith('helm', false);
});
test('findHelm() - change access permissions and find the helm in given directory', () => {
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
test('findHelm() - change access permissions and find the helm in given directory', () => {
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
expect(helmUtil.findHelm('mainFolder')).toBe(path.join('mainFolder', 'helm.exe'));
expect(fs.chmodSync).toBeCalledWith('mainFolder', '777');
expect(fs.readdirSync).toBeCalledWith('mainFolder');
expect(fs.statSync).toBeCalledWith(path.join('mainFolder', 'helm.exe'));
});
});
expect(helmUtil.findHelm('mainFolder')).toBe(
path.join('mainFolder', 'helm.exe')
)
expect(fs.chmodSync).toBeCalledWith('mainFolder', '777')
expect(fs.readdirSync).toBeCalledWith('mainFolder')
expect(fs.statSync).toBeCalledWith(path.join('mainFolder', 'helm.exe'))
})
})

Просмотреть файл

@ -1,97 +1,108 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as path from 'path'
import * as fs from 'fs'
import * as util from 'util'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import * as io from '@actions/io'
import {
getExecutableExtension,
isEqual,
LATEST,
setCachedToolPath,
getStableVerison
} from './utilities'
import * as path from 'path';
import * as fs from 'fs';
import * as util from 'util';
import * as toolCache from '@actions/tool-cache';
import * as core from '@actions/core';
import * as io from '@actions/io';
import { getExecutableExtension, isEqual, LATEST, setCachedToolPath, getStableVerison } from "./utilities"
const helmToolName = 'helm';
const helmToolName = 'helm'
export interface NameValuePair {
name: string;
value: string;
name: string
value: string
}
export function walkSync (dir, filelist = [], fileToFind) {
const files = fs.readdirSync(dir);
files.forEach(function(file) {
export function walkSync(dir, filelist = [], fileToFind) {
const files = fs.readdirSync(dir)
files.forEach(function (file) {
if (fs.statSync(path.join(dir, file)).isDirectory()) {
filelist = walkSync(path.join(dir, file), filelist, fileToFind);
filelist = walkSync(path.join(dir, file), filelist, fileToFind)
} else {
core.debug(file)
if (file == fileToFind) {
filelist.push(path.join(dir, file))
}
}
else {
core.debug(file);
if(file == fileToFind)
{
filelist.push(path.join(dir, file));
}
}
});
return filelist;
};
})
return filelist
}
export async function downloadHelm(version: string): Promise<string> {
if(!version){
version = await getStableVerison(helmToolName);
}
let cachedToolpath = toolCache.find(helmToolName, version);
if (!cachedToolpath) {
cachedToolpath = await setCachedToolPath(helmToolName, version);
}
const helmpath = findHelm(cachedToolpath);
if (!helmpath) {
throw new Error(util.format("Helm executable not found in path ", cachedToolpath));
}
if (!version) {
version = await getStableVerison(helmToolName)
}
let cachedToolpath = toolCache.find(helmToolName, version)
if (!cachedToolpath) {
cachedToolpath = await setCachedToolPath(helmToolName, version)
}
const helmpath = findHelm(cachedToolpath)
if (!helmpath) {
throw new Error(
util.format('Helm executable not found in path ', cachedToolpath)
)
}
fs.chmodSync(helmpath, '777');
return helmpath;
fs.chmodSync(helmpath, '777')
return helmpath
}
export function findHelm(rootFolder: string): string {
fs.chmodSync(rootFolder, '777');
const filelist: string[] = [];
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension());
if (!filelist) {
throw new Error(util.format("Helm executable not found in path ", rootFolder));
}
else {
return filelist[0];
}
fs.chmodSync(rootFolder, '777')
const filelist: string[] = []
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension())
if (!filelist) {
throw new Error(
util.format('Helm executable not found in path ', rootFolder)
)
} else {
return filelist[0]
}
}
export async function getHelmPath() {
let helmPath = "";
const version = core.getInput('helm-version', { required: false });
if (version) {
if ( !!version && version != LATEST ){
helmPath = toolCache.find(helmToolName, version);
}
if (!helmPath) {
helmPath = await installHelm(version);
}
} else {
helmPath = await io.which(helmToolName, false);
if (!helmPath) {
const allVersions = toolCache.findAllVersions(helmToolName);
helmPath = allVersions.length > 0 ? toolCache.find(helmToolName, allVersions[0]) : '';
if (!helmPath) {
throw new Error('helm is not installed, either add setup-helm action or provide "helm-version" input to download helm');
}
helmPath = path.join(helmPath, `helm${getExecutableExtension()}`);
}
}
let helmPath = ''
const version = core.getInput('helm-version', {required: false})
if (version) {
if (!!version && version != LATEST) {
helmPath = toolCache.find(helmToolName, version)
}
if (!helmPath) {
helmPath = await installHelm(version)
}
} else {
helmPath = await io.which(helmToolName, false)
if (!helmPath) {
const allVersions = toolCache.findAllVersions(helmToolName)
helmPath =
allVersions.length > 0
? toolCache.find(helmToolName, allVersions[0])
: ''
if (!helmPath) {
throw new Error(
'helm is not installed, either add setup-helm action or provide "helm-version" input to download helm'
)
}
helmPath = path.join(helmPath, `helm${getExecutableExtension()}`)
}
}
core.debug(util.format("Helm executable path %s", helmPath));
return helmPath;
core.debug(util.format('Helm executable path %s', helmPath))
return helmPath
}
export async function installHelm(version: string) {
if (isEqual(version, LATEST)) {
version = await getStableVerison(helmToolName);
}
core.debug(util.format("Downloading helm version %s", version));
return await downloadHelm(version);
if (isEqual(version, LATEST)) {
version = await getStableVerison(helmToolName)
}
core.debug(util.format('Downloading helm version %s', version))
return await downloadHelm(version)
}

Просмотреть файл

@ -1,115 +1,142 @@
import * as komposeUtil from './kompose-util';
import * as os from 'os';
import * as fs from 'fs';
import * as path from 'path';
import * as toolCache from '@actions/tool-cache';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as komposeUtil from './kompose-util'
import * as os from 'os'
import * as fs from 'fs'
import * as path from 'path'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import * as io from '@actions/io'
describe('Testing all funcitons in kompose-util file.', () => {
test('downloadKompose() - return path to kompose from toolCache', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
test('downloadKompose() - return path to kompose from toolCache', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(
path.join('pathToCachedTool', 'kompose.exe')
)
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedTool', 'kompose.exe'),
0o100
)
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
})
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kompose.exe'), 0o100);
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
});
test('downloadKompose() - download kompose, cache it and return path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
test('downloadKompose() - download kompose, cache it and return path', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool');
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(
path.join('pathToCachedTool', 'kompose.exe')
)
expect(toolCache.downloadTool).toBeCalledWith(
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe'
)
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedTool', 'kompose.exe'),
0o100
)
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
})
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
expect(toolCache.downloadTool).toBeCalledWith('https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe');
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kompose.exe'), 0o100);
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
});
test('downloadKompose() - throw error when unable to download', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
throw 'Unable to download.'
})
test("downloadKompose() - throw error when unable to download", async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Unable to download.'});
await expect(komposeUtil.downloadKompose('v1.18.0')).rejects.toThrow(
'Failed to download the kompose from https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe. Error: Unable to download.'
)
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
})
await expect(komposeUtil.downloadKompose('v1.18.0')).rejects.toThrow("Failed to download the kompose from https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe. Error: Unable to download.");
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
});
test('installKompose() - return path kompose from cache', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(core, 'debug').mockImplementation()
test("installKompose() - return path kompose from cache", async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(core, 'debug').mockImplementation();
expect(await komposeUtil.installKompose('v1.20.0')).toBe(
path.join('pathToCachedTool', 'kompose.exe')
)
})
expect(await komposeUtil.installKompose('v1.20.0')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
});
test('installKompose() - return path to kompose v1.18.0 when input is latest', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(core, 'debug').mockImplementation()
test("installKompose() - return path to kompose v1.18.0 when input is latest", async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(core, 'debug').mockImplementation();
expect(await komposeUtil.installKompose('latest')).toBe(
path.join('pathToCachedTool', 'kompose.exe')
)
})
expect(await komposeUtil.installKompose('latest')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
});
test('getKomposePath() - return path to latest version kompose from toolCache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('latest')
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
test("getKomposePath() - return path to latest version kompose from toolCache", async () => {
jest.spyOn(core, 'getInput').mockReturnValue('latest');
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
expect(await komposeUtil.getKomposePath()).toBe(
path.join('pathToCachedTool', 'kompose.exe')
)
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
})
expect(await komposeUtil.getKomposePath()).toBe(path.join('pathToCachedTool', 'kompose.exe'));
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
});
test('getKomposePath() - return path to specified version kompose from toolCache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0')
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
test("getKomposePath() - return path to specified version kompose from toolCache", async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0');
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
expect(await komposeUtil.getKomposePath()).toBe('pathToCachedTool')
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0')
})
expect(await komposeUtil.getKomposePath()).toBe('pathToCachedTool');
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0');
});
test('getKomposePath() - return path to any version executable when input is not given', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('pathToTool')
test("getKomposePath() - return path to any version executable when input is not given", async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('pathToTool');
expect(await komposeUtil.getKomposePath()).toBe('pathToTool')
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
expect(io.which).toBeCalledWith('kompose', false)
})
expect(await komposeUtil.getKomposePath()).toBe('pathToTool');
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
expect(io.which).toBeCalledWith('kompose', false);
});
test('getKomposePath() - return path to any version kompose from toolCache when input is not given', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('')
jest
.spyOn(toolCache, 'findAllVersions')
.mockReturnValue(['v2.0.0', 'v2.0.1'])
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
test("getKomposePath() - return path to any version kompose from toolCache when input is not given", async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('');
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['v2.0.0', 'v2.0.1']);
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
expect(await komposeUtil.getKomposePath()).toBe(
path.join('pathToTool', 'kompose.exe')
)
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
expect(io.which).toBeCalledWith('kompose', false)
expect(toolCache.findAllVersions).toBeCalledWith('kompose')
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0')
})
expect(await komposeUtil.getKomposePath()).toBe(path.join('pathToTool', 'kompose.exe'));
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
expect(io.which).toBeCalledWith('kompose', false);
expect(toolCache.findAllVersions).toBeCalledWith('kompose');
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0');
});
test('getKomposePath() - throw error when version input is not given and not kompose already exists', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('')
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([])
test("getKomposePath() - throw error when version input is not given and not kompose already exists", async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('');
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([]);
await expect(komposeUtil.getKomposePath()).rejects.toThrow('kompose is not installed, provide "kompose-version" input to download kompose');
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
expect(io.which).toBeCalledWith('kompose', false);
expect(toolCache.findAllVersions).toBeCalledWith('kompose');
});
});
await expect(komposeUtil.getKomposePath()).rejects.toThrow(
'kompose is not installed, provide "kompose-version" input to download kompose'
)
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
expect(io.which).toBeCalledWith('kompose', false)
expect(toolCache.findAllVersions).toBeCalledWith('kompose')
})
})

Просмотреть файл

@ -1,58 +1,76 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as path from 'path';
import * as fs from 'fs';
import * as util from 'util';
import * as toolCache from '@actions/tool-cache';
import * as core from '@actions/core';
import * as io from '@actions/io';
import { getExecutableExtension, isEqual, setCachedToolPath, LATEST } from "./utilities"
import * as path from 'path'
import * as fs from 'fs'
import * as util from 'util'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import * as io from '@actions/io'
import {
getExecutableExtension,
isEqual,
setCachedToolPath,
LATEST
} from './utilities'
const komposeToolName = 'kompose';
const stableKomposeVersion = "v1.18.0";
const komposeToolName = 'kompose'
const stableKomposeVersion = 'v1.18.0'
export async function getKomposePath() {
let komposePath = "";
const version = core.getInput('kompose-version', { required: false });
if (version) {
if ( !!version && version != LATEST ){
komposePath = toolCache.find(komposeToolName, version);
}
let komposePath = ''
const version = core.getInput('kompose-version', {required: false})
if (version) {
if (!!version && version != LATEST) {
komposePath = toolCache.find(komposeToolName, version)
}
if (!komposePath) {
komposePath = await installKompose(version);
}
} else {
komposePath = await io.which(komposeToolName, false);
if (!komposePath) {
const allVersions = toolCache.findAllVersions(komposeToolName);
komposePath = allVersions.length > 0 ? toolCache.find(komposeToolName, allVersions[0]) : '';
if (!komposePath) {
throw new Error('kompose is not installed, provide "kompose-version" input to download kompose');
}
komposePath = path.join(komposePath, `kompose${getExecutableExtension()}`);
}
}
if (!komposePath) {
komposePath = await installKompose(version)
}
} else {
komposePath = await io.which(komposeToolName, false)
if (!komposePath) {
const allVersions = toolCache.findAllVersions(komposeToolName)
komposePath =
allVersions.length > 0
? toolCache.find(komposeToolName, allVersions[0])
: ''
if (!komposePath) {
throw new Error(
'kompose is not installed, provide "kompose-version" input to download kompose'
)
}
komposePath = path.join(
komposePath,
`kompose${getExecutableExtension()}`
)
}
}
return komposePath;
return komposePath
}
export async function downloadKompose(version: string=stableKomposeVersion): Promise<string> {
let cachedToolpath = toolCache.find(komposeToolName, version);
if (!cachedToolpath) {
cachedToolpath = await setCachedToolPath(komposeToolName, version);
}
export async function downloadKompose(
version: string = stableKomposeVersion
): Promise<string> {
let cachedToolpath = toolCache.find(komposeToolName, version)
if (!cachedToolpath) {
cachedToolpath = await setCachedToolPath(komposeToolName, version)
}
const komposePath = path.join(cachedToolpath, komposeToolName + getExecutableExtension());
fs.chmodSync(komposePath, 0o100); // execute/search by owner permissions to the tool
return komposePath;
const komposePath = path.join(
cachedToolpath,
komposeToolName + getExecutableExtension()
)
fs.chmodSync(komposePath, 0o100) // execute/search by owner permissions to the tool
return komposePath
}
export async function installKompose(version: string) {
if (isEqual(version, LATEST)) {
version = stableKomposeVersion;
}
core.debug(util.format("Downloading kompose version %s", version));
return await downloadKompose(version);
if (isEqual(version, LATEST)) {
version = stableKomposeVersion
}
core.debug(util.format('Downloading kompose version %s', version))
return await downloadKompose(version)
}

Просмотреть файл

@ -1,123 +1,158 @@
import * as kubectlUtil from './kubectl-util';
import * as os from 'os';
import * as fs from 'fs';
import * as path from 'path';
import * as toolCache from '@actions/tool-cache';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as utils from './utilities';
import * as kubectlUtil from './kubectl-util'
import * as os from 'os'
import * as fs from 'fs'
import * as path from 'path'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import * as io from '@actions/io'
import * as utils from './utilities'
describe('Testing all funcitons in kubectl-util file.', () => {
test('downloadKubectl() - download kubectl, add it to toolCache and return path to it', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(fs, 'chmodSync').mockImplementation()
test('downloadKubectl() - download kubectl, add it to toolCache and return path to it', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'chmodSync').mockImplementation();
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(
path.join('pathToCachedTool', 'kubectl.exe')
)
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
expect(toolCache.downloadTool).toBeCalled()
expect(toolCache.cacheFile).toBeCalled()
expect(os.type).toBeCalled()
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedTool', 'kubectl.exe'),
'777'
)
})
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(path.join('pathToCachedTool', 'kubectl.exe'));
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
expect(toolCache.downloadTool).toBeCalled();
expect(toolCache.cacheFile).toBeCalled();
expect(os.type).toBeCalled();
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kubectl.exe'), '777');
});
test('downloadKubectl() - throw DownloadKubectlFailed error when unable to download kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest
.spyOn(toolCache, 'downloadTool')
.mockRejectedValue('Unable to download kubectl.')
test('downloadKubectl() - throw DownloadKubectlFailed error when unable to download kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockRejectedValue('Unable to download kubectl.');
await expect(kubectlUtil.downloadKubectl('v1.15.0')).rejects.toThrow(
'Failed to download the kubectl from https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe. Error: Unable to download kubectl.'
)
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
expect(toolCache.downloadTool).toBeCalled()
})
await expect(kubectlUtil.downloadKubectl('v1.15.0')).rejects.toThrow('Failed to download the kubectl from https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe. Error: Unable to download kubectl.');
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
expect(toolCache.downloadTool).toBeCalled();
});
test('downloadKubectl() - return path to existing cache of kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
test('downloadKubectl() - return path to existing cache of kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(
path.join('pathToCachedTool', 'kubectl.exe')
)
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
expect(os.type).toBeCalled()
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedTool', 'kubectl.exe'),
'777'
)
})
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(path.join('pathToCachedTool', 'kubectl.exe'));
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
expect(os.type).toBeCalled();
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kubectl.exe'), '777');
});
test('installKubectl() - return its path to installed kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
throw 'Error!!'
})
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => [
'kubectl.exe' as unknown as fs.Dirent
])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(core, 'debug').mockImplementation()
test('installKubectl() - return its path to installed kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir');
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Error!!'});
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['kubectl.exe' as unknown as fs.Dirent]);
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
return { isDirectory: () => isDirectory } as fs.Stats;
});
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(core, 'debug').mockImplementation();
expect(await kubectlUtil.installKubectl('v1.15.0')).toBe(
path.join('pathToCachedDir', 'kubectl.exe')
)
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
})
expect(await kubectlUtil.installKubectl('v1.15.0')).toBe(path.join('pathToCachedDir', 'kubectl.exe'));
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
});
test('installKubectl() - download and return path to latest kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(fs, 'readFileSync').mockReturnValue('v1.15.0')
jest.spyOn(core, 'debug').mockImplementation()
test('installKubectl() - download and return path to latest kubectl', async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('');
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
jest.spyOn(fs, 'chmodSync').mockImplementation();
jest.spyOn(fs, 'readFileSync').mockReturnValue('v1.15.0');
jest.spyOn(core, 'debug').mockImplementation();
expect(await kubectlUtil.installKubectl('latest')).toBe(
path.join('pathToCachedTool', 'kubectl.exe')
)
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
expect(toolCache.downloadTool).toBeCalled()
expect(toolCache.cacheFile).toBeCalled()
expect(os.type).toBeCalled()
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedTool', 'kubectl.exe'),
'777'
)
})
expect(await kubectlUtil.installKubectl('latest')).toBe(path.join('pathToCachedTool', 'kubectl.exe'));
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
expect(toolCache.downloadTool).toBeCalled();
expect(toolCache.cacheFile).toBeCalled();
expect(os.type).toBeCalled();
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kubectl.exe'), '777');
});
test('getKubectlPath() - throw if version is not provided and no kubectl is already present', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('')
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([])
test('getKubectlPath() - throw if version is not provided and no kubectl is already present', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('');
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([]);
await expect(kubectlUtil.getKubectlPath()).rejects.toThrow(
'Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl'
)
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
expect(io.which).toBeCalledWith('kubectl', false)
expect(toolCache.findAllVersions).toBeCalledWith('kubectl')
})
await expect(kubectlUtil.getKubectlPath()).rejects.toThrow('Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl');
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
expect(io.which).toBeCalledWith('kubectl', false);
expect(toolCache.findAllVersions).toBeCalledWith('kubectl');
});
test('getKubectlPath() - return installed version of kubectl if input not provided', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('pathToKubectl')
test('getKubectlPath() - return installed version of kubectl if input not provided', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('pathToKubectl');
expect(await kubectlUtil.getKubectlPath()).toBe('pathToKubectl')
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
expect(io.which).toBeCalledWith('kubectl', false)
})
expect(await kubectlUtil.getKubectlPath()).toBe('pathToKubectl');
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
expect(io.which).toBeCalledWith('kubectl', false);
});
test('getKubectlPath() - return any version of kubectl from toolCache if input not provided', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('')
jest.spyOn(io, 'which').mockResolvedValue('')
jest
.spyOn(toolCache, 'findAllVersions')
.mockReturnValue(['v2.0.0', 'v1.0.0'])
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedKubectl')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
test('getKubectlPath() - return any version of kubectl from toolCache if input not provided', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('');
jest.spyOn(io, 'which').mockResolvedValue('');
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['v2.0.0', 'v1.0.0']);
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedKubectl');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
expect(await kubectlUtil.getKubectlPath()).toBe(
path.join('pathToCachedKubectl', 'kubectl.exe')
)
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
expect(io.which).toBeCalledWith('kubectl', false)
expect(toolCache.findAllVersions).toBeCalledWith('kubectl')
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0')
})
expect(await kubectlUtil.getKubectlPath()).toBe(path.join('pathToCachedKubectl', 'kubectl.exe'));
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
expect(io.which).toBeCalledWith('kubectl', false);
expect(toolCache.findAllVersions).toBeCalledWith('kubectl');
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0');
});
test('getKubectlPath() - return path to specified version kubectl from toolCache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0')
jest.spyOn(toolCache, 'find').mockReturnValue('pathToKubectl')
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
test('getKubectlPath() - return path to specified version kubectl from toolCache', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0');
jest.spyOn(toolCache, 'find').mockReturnValue('pathToKubectl');
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
expect(await kubectlUtil.getKubectlPath()).toBe(path.join('pathToKubectl', 'kubectl.exe'));
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0');
});
});
expect(await kubectlUtil.getKubectlPath()).toBe(
path.join('pathToKubectl', 'kubectl.exe')
)
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0')
})
})

Просмотреть файл

@ -1,62 +1,82 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as path from 'path';
import * as fs from 'fs';
import * as util from 'util';
import * as toolCache from '@actions/tool-cache';
import * as core from '@actions/core';
import * as io from '@actions/io';
import { getExecutableExtension, isEqual, LATEST, setCachedToolPath, getStableVerison} from "./utilities"
import * as path from 'path'
import * as fs from 'fs'
import * as util from 'util'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import * as io from '@actions/io'
import {
getExecutableExtension,
isEqual,
LATEST,
setCachedToolPath,
getStableVerison
} from './utilities'
const kubectlToolName = 'kubectl';
const kubectlToolName = 'kubectl'
export async function downloadKubectl(version: string): Promise<string> {
if(!version){
version = await getStableVerison(kubectlToolName);
}
let cachedToolpath = toolCache.find(kubectlToolName, version);
if (!version) {
version = await getStableVerison(kubectlToolName)
}
let cachedToolpath = toolCache.find(kubectlToolName, version)
if (!cachedToolpath) {
cachedToolpath = await setCachedToolPath(kubectlToolName, version);
}
if (!cachedToolpath) {
cachedToolpath = await setCachedToolPath(kubectlToolName, version)
}
const kubectlPath = path.join(cachedToolpath, kubectlToolName + getExecutableExtension());
fs.chmodSync(kubectlPath, '777');
return kubectlPath;
const kubectlPath = path.join(
cachedToolpath,
kubectlToolName + getExecutableExtension()
)
fs.chmodSync(kubectlPath, '777')
return kubectlPath
}
export async function getKubectlPath() {
let kubectlPath = "";
const version = core.getInput('kubectl-version', { required: false });
if (version) {
if ( !!version && version != LATEST ){
const cachedToolPath = toolCache.find(kubectlToolName, version);
kubectlPath = path.join(cachedToolPath, kubectlToolName + getExecutableExtension())
}
let kubectlPath = ''
const version = core.getInput('kubectl-version', {required: false})
if (version) {
if (!!version && version != LATEST) {
const cachedToolPath = toolCache.find(kubectlToolName, version)
kubectlPath = path.join(
cachedToolPath,
kubectlToolName + getExecutableExtension()
)
}
if (!kubectlPath) {
kubectlPath = await installKubectl(version);
}
} else {
kubectlPath = await io.which(kubectlToolName, false);
if (!kubectlPath) {
const allVersions = toolCache.findAllVersions(kubectlToolName);
kubectlPath = allVersions.length > 0 ? toolCache.find(kubectlToolName, allVersions[0]) : '';
if (!kubectlPath) {
throw new Error('Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl');
}
kubectlPath = path.join(kubectlPath, `kubectl${getExecutableExtension()}`);
}
}
if (!kubectlPath) {
kubectlPath = await installKubectl(version)
}
} else {
kubectlPath = await io.which(kubectlToolName, false)
if (!kubectlPath) {
const allVersions = toolCache.findAllVersions(kubectlToolName)
kubectlPath =
allVersions.length > 0
? toolCache.find(kubectlToolName, allVersions[0])
: ''
if (!kubectlPath) {
throw new Error(
'Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl'
)
}
kubectlPath = path.join(
kubectlPath,
`kubectl${getExecutableExtension()}`
)
}
}
return kubectlPath
return kubectlPath
}
export async function installKubectl(version: string) {
if (isEqual(version, LATEST)) {
version = await getStableVerison(kubectlToolName);
}
core.debug(util.format("Downloading kubectl version %s", version));
return await downloadKubectl(version);
if (isEqual(version, LATEST)) {
version = await getStableVerison(kubectlToolName)
}
core.debug(util.format('Downloading kubectl version %s', version))
return await downloadKubectl(version)
}

Просмотреть файл

@ -1,294 +1,483 @@
import * as helmUtil from './helm-util';
import * as kubectlUtil from './kubectl-util';
import * as komposeUtil from './kompose-util';
import * as utils from './utilities';
import { KustomizeRenderEngine, KomposeRenderEngine, HelmRenderEngine, run } from './run';
import * as ioUtil from '@actions/io/lib/io-util';
import * as fs from 'fs';
import * as path from 'path';
import * as core from '@actions/core';
import { ExecOptions } from "@actions/exec/lib/interfaces";
import * as helmUtil from './helm-util'
import * as kubectlUtil from './kubectl-util'
import * as komposeUtil from './kompose-util'
import * as utils from './utilities'
import {
KustomizeRenderEngine,
KomposeRenderEngine,
HelmRenderEngine,
run
} from './run'
import * as ioUtil from '@actions/io/lib/io-util'
import * as fs from 'fs'
import * as path from 'path'
import * as core from '@actions/core'
import {ExecOptions} from '@actions/exec/lib/interfaces'
var mockStatusCode, stdOutMessage, stdErrMessage;
var mockStatusCode, stdOutMessage, stdErrMessage
const mockExecFn = jest.fn().mockImplementation((toolPath, args, options) => {
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage);
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage);
return mockStatusCode;
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage)
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage)
return mockStatusCode
})
jest.mock('@actions/exec/lib/toolrunner', () => {
return {
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
return {
exec: () => mockExecFn(toolPath, args, options)
}
})
}
});
return {
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
return {
exec: () => mockExecFn(toolPath, args, options)
}
})
}
})
describe('Test all functions in run file', () => {
test('KustomizeRenderEngine() - throw error if kubectl doesn\'t meet required version', async () => {
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
const kubectlVersionResponse = {
'stdout': JSON.stringify({
"clientVersion": {
"major": "0",
"minor": "18",
}
})
};
jest.spyOn(utils, 'execCommand').mockResolvedValue(kubectlVersionResponse as utils.ExecResult);
await expect((new KustomizeRenderEngine()).bake(false)).rejects.toThrow('kubectl client version equal to v1.14 or higher is required to use kustomize features');
expect(kubectlUtil.getKubectlPath).toBeCalled();
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
});
test('KustomizeRenderEngine() - validate kubetl and bake using kustomize', async () => {
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
const responseStdout = JSON.stringify({
"clientVersion": {
"major": "1",
"minor": "18",
test("KustomizeRenderEngine() - throw error if kubectl doesn't meet required version", async () => {
jest
.spyOn(kubectlUtil, 'getKubectlPath')
.mockResolvedValue('pathToKubectl')
const kubectlVersionResponse = {
stdout: JSON.stringify({
clientVersion: {
major: '0',
minor: '18'
}
});
const kubectlVersionResponse = {
'stdout': responseStdout
};
const kustomizeResponse = {
'stdout': 'kustomizeOutput'
};
jest.spyOn(utils, 'execCommand').mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult).mockResolvedValueOnce(kustomizeResponse as utils.ExecResult);
jest.spyOn(core, 'getInput').mockImplementation((inputName) => {
if (inputName == "kustomizationPath") return 'pathToKustomization';
if (inputName == "arguments") return 'additionalArguments';
})
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
jest.spyOn(fs, 'writeFileSync').mockImplementation();
process.env['RUNNER_TEMP'] = 'tempDir';
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(core, 'setOutput').mockImplementation();
jest.spyOn(console, 'log').mockImplementation();
})
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValue(kubectlVersionResponse as utils.ExecResult)
expect(await (new KustomizeRenderEngine()).bake(true)).toBeUndefined();
expect(kubectlUtil.getKubectlPath).toBeCalled();
await expect(new KustomizeRenderEngine().bake(false)).rejects.toThrow(
'kubectl client version equal to v1.14 or higher is required to use kustomize features'
)
expect(kubectlUtil.getKubectlPath).toBeCalled()
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
'version',
'--client=true',
'-o',
'json'
])
})
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['kustomize', 'pathToKustomization', 'additionalArguments'], { silent: true } as ExecOptions);
test('KustomizeRenderEngine() - validate kubetl and bake using kustomize', async () => {
jest
.spyOn(kubectlUtil, 'getKubectlPath')
.mockResolvedValue('pathToKubectl')
const responseStdout = JSON.stringify({
clientVersion: {
major: '1',
minor: '18'
}
})
const kubectlVersionResponse = {
stdout: responseStdout
}
const kustomizeResponse = {
stdout: 'kustomizeOutput'
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult)
.mockResolvedValueOnce(kustomizeResponse as utils.ExecResult)
jest.spyOn(core, 'getInput').mockImplementation((inputName) => {
if (inputName == 'kustomizationPath') return 'pathToKustomization'
if (inputName == 'arguments') return 'additionalArguments'
})
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
jest.spyOn(fs, 'writeFileSync').mockImplementation()
process.env['RUNNER_TEMP'] = 'tempDir'
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(core, 'setOutput').mockImplementation()
jest.spyOn(console, 'log').mockImplementation()
expect(core.getInput).toBeCalledWith('kustomizationPath', { required: true });
expect(fs.writeFileSync).toBeCalledWith(path.join('tempDir', 'baked-template-12345678.yaml'), 'kustomizeOutput');
expect(core.setOutput).toBeCalledWith('manifestsBundle', path.join('tempDir', 'baked-template-12345678.yaml'));
});
expect(await new KustomizeRenderEngine().bake(true)).toBeUndefined()
expect(kubectlUtil.getKubectlPath).toBeCalled()
test('KustomizeRenderEngine() - multiple additional arguments with leading/trailing spaces', async () => {
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
const kubectlVersionResponse = {
'stdout': JSON.stringify({
"clientVersion": {
"major": "1",
"minor": "18",
}
})
};
const kustomizeResponse = {
'stdout': 'kustomizeOutput'
};
jest.spyOn(utils, 'execCommand').mockResolvedValue(kubectlVersionResponse as utils.ExecResult);
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == "kustomizationPath") return 'pathToKustomization';
if (inputName == "arguments") return ' additional \n Arguments ';
})
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
jest.spyOn(fs, 'writeFileSync').mockImplementation();
process.env['RUNNER_TEMP'] = 'tempDir';
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(core, 'setOutput').mockImplementation();
jest.spyOn(console, 'log').mockImplementation();
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
'version',
'--client=true',
'-o',
'json'
])
expect(utils.execCommand).toBeCalledWith(
'pathToKubectl',
['kustomize', 'pathToKustomization', 'additionalArguments'],
{silent: true} as ExecOptions
)
expect(await (new KustomizeRenderEngine()).bake(true)).toBeUndefined();
expect(kubectlUtil.getKubectlPath).toBeCalled();
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['kustomize', 'pathToKustomization', 'additional', 'Arguments'], { silent: true } as ExecOptions);
});
expect(core.getInput).toBeCalledWith('kustomizationPath', {
required: true
})
expect(fs.writeFileSync).toBeCalledWith(
path.join('tempDir', 'baked-template-12345678.yaml'),
'kustomizeOutput'
)
expect(core.setOutput).toBeCalledWith(
'manifestsBundle',
path.join('tempDir', 'baked-template-12345678.yaml')
)
})
test('KustomizeRenderEngine() - multiple additional argument', async () => {
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
const kubectlVersionResponse = {
'stdout': JSON.stringify({
"clientVersion": {
"major": "1",
"minor": "18",
}
})
};
const kustomizeResponse = {
'stdout': 'kustomizeOutput'
};
jest.spyOn(utils, 'execCommand').mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult).mockResolvedValueOnce(kustomizeResponse as utils.ExecResult);
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == "kustomizationPath") return 'pathToKustomization';
if (inputName == "arguments") return 'add1 tional,\nArguments\nnore\nargu ments';
})
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
jest.spyOn(fs, 'writeFileSync').mockImplementation();
process.env['RUNNER_TEMP'] = 'tempDir';
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(core, 'setOutput').mockImplementation();
jest.spyOn(console, 'log').mockImplementation();
test('KustomizeRenderEngine() - multiple additional arguments with leading/trailing spaces', async () => {
jest
.spyOn(kubectlUtil, 'getKubectlPath')
.mockResolvedValue('pathToKubectl')
const kubectlVersionResponse = {
stdout: JSON.stringify({
clientVersion: {
major: '1',
minor: '18'
}
})
}
const kustomizeResponse = {
stdout: 'kustomizeOutput'
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValue(kubectlVersionResponse as utils.ExecResult)
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == 'kustomizationPath') return 'pathToKustomization'
if (inputName == 'arguments') return ' additional \n Arguments '
})
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
jest.spyOn(fs, 'writeFileSync').mockImplementation()
process.env['RUNNER_TEMP'] = 'tempDir'
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(core, 'setOutput').mockImplementation()
jest.spyOn(console, 'log').mockImplementation()
expect(await (new KustomizeRenderEngine()).bake(true)).toBeUndefined();
expect(kubectlUtil.getKubectlPath).toBeCalled();
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['kustomize', 'pathToKustomization', 'add1 tional', 'Arguments', 'nore', 'argu ments'], { silent: true } as ExecOptions);
})
expect(await new KustomizeRenderEngine().bake(true)).toBeUndefined()
expect(kubectlUtil.getKubectlPath).toBeCalled()
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
'version',
'--client=true',
'-o',
'json'
])
expect(utils.execCommand).toBeCalledWith(
'pathToKubectl',
['kustomize', 'pathToKustomization', 'additional', 'Arguments'],
{silent: true} as ExecOptions
)
})
test('KomposeRenderEngine() - throw error if unable to find temp directory', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('pathToKompose');
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
jest.spyOn(komposeUtil, 'getKomposePath').mockResolvedValue('pathToKompose');
process.env['RUNNER_TEMP'] = '';
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(console, 'log').mockImplementation();
test('KustomizeRenderEngine() - multiple additional argument', async () => {
jest
.spyOn(kubectlUtil, 'getKubectlPath')
.mockResolvedValue('pathToKubectl')
const kubectlVersionResponse = {
stdout: JSON.stringify({
clientVersion: {
major: '1',
minor: '18'
}
})
}
const kustomizeResponse = {
stdout: 'kustomizeOutput'
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult)
.mockResolvedValueOnce(kustomizeResponse as utils.ExecResult)
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == 'kustomizationPath') return 'pathToKustomization'
if (inputName == 'arguments')
return 'add1 tional,\nArguments\nnore\nargu ments'
})
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
jest.spyOn(fs, 'writeFileSync').mockImplementation()
process.env['RUNNER_TEMP'] = 'tempDir'
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(core, 'setOutput').mockImplementation()
jest.spyOn(console, 'log').mockImplementation()
await expect((new KomposeRenderEngine()).bake(false)).rejects.toThrow('Unable to create temp directory.');
expect(komposeUtil.getKomposePath).toBeCalled();
});
expect(await new KustomizeRenderEngine().bake(true)).toBeUndefined()
expect(kubectlUtil.getKubectlPath).toBeCalled()
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
'version',
'--client=true',
'-o',
'json'
])
expect(utils.execCommand).toBeCalledWith(
'pathToKubectl',
[
'kustomize',
'pathToKustomization',
'add1 tional',
'Arguments',
'nore',
'argu ments'
],
{silent: true} as ExecOptions
)
})
test('KomposeRenderEngine() - bake using kompose', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('pathToDockerCompose');
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
jest.spyOn(komposeUtil, 'getKomposePath').mockResolvedValue('pathToKompose');
process.env['RUNNER_TEMP'] = 'tempDir';
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'setOutput').mockImplementation();
test('KomposeRenderEngine() - throw error if unable to find temp directory', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('pathToKompose')
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
jest
.spyOn(komposeUtil, 'getKomposePath')
.mockResolvedValue('pathToKompose')
process.env['RUNNER_TEMP'] = ''
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(console, 'log').mockImplementation()
expect(await (new KomposeRenderEngine()).bake(true)).toBeUndefined();
expect(komposeUtil.getKomposePath).toBeCalled();
expect(utils.execCommand).toBeCalledWith('pathToKompose', ['convert', '-f', 'pathToDockerCompose', '-o', path.join('tempDir', 'baked-template-12345678.yaml')], {"silent": true});
expect(core.setOutput).toBeCalledWith('manifestsBundle', path.join('tempDir', 'baked-template-12345678.yaml'));
});
await expect(new KomposeRenderEngine().bake(false)).rejects.toThrow(
'Unable to create temp directory.'
)
expect(komposeUtil.getKomposePath).toBeCalled()
})
test('run() - throw error on wrong input from render-engine', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('someRenderEngine');
test('KomposeRenderEngine() - bake using kompose', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('pathToDockerCompose')
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
jest
.spyOn(komposeUtil, 'getKomposePath')
.mockResolvedValue('pathToKompose')
process.env['RUNNER_TEMP'] = 'tempDir'
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'setOutput').mockImplementation()
await expect(run()).rejects.toThrow('Unknown render engine');
});
expect(await new KomposeRenderEngine().bake(true)).toBeUndefined()
expect(komposeUtil.getKomposePath).toBeCalled()
expect(utils.execCommand).toBeCalledWith(
'pathToKompose',
[
'convert',
'-f',
'pathToDockerCompose',
'-o',
path.join('tempDir', 'baked-template-12345678.yaml')
],
{silent: true}
)
expect(core.setOutput).toBeCalledWith(
'manifestsBundle',
path.join('tempDir', 'baked-template-12345678.yaml')
)
})
test('run() - throw error if bake fails', async () => {
jest.spyOn(core, 'getInput').mockReturnValueOnce('kompose').mockReturnValueOnce('pathToKompose');
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
jest.spyOn(komposeUtil, 'getKomposePath').mockResolvedValue('pathToKompose');
process.env['RUNNER_TEMP'] = '';
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
test('run() - throw error on wrong input from render-engine', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('someRenderEngine')
await expect(run()).rejects.toThrow('Failed to run bake action. Error: Error: Unable to create temp directory.');
});
await expect(run()).rejects.toThrow('Unknown render engine')
})
test('HelmRenderEngine() - bake manifest using helm', async () => {
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
jest.spyOn(core, 'getInput').mockReturnValueOnce('pathToHelmChart').mockReturnValueOnce('releaseName');
jest.spyOn(console, 'log').mockImplementation();
mockStatusCode = 0;
stdOutMessage = 'v2.9.1';
process.env['RUNNER_TEMP'] = 'tempDirPath';
jest.spyOn(fs, 'writeFileSync').mockImplementation();
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'setOutput').mockImplementation();
test('run() - throw error if bake fails', async () => {
jest
.spyOn(core, 'getInput')
.mockReturnValueOnce('kompose')
.mockReturnValueOnce('pathToKompose')
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
jest
.spyOn(komposeUtil, 'getKomposePath')
.mockResolvedValue('pathToKompose')
process.env['RUNNER_TEMP'] = ''
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
const execResult = {
'stdout': 'test output'
};
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
await expect(run()).rejects.toThrow(
'Failed to run bake action. Error: Error: Unable to create temp directory.'
)
})
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['dependency', 'update', 'pathToHelmChart'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], {"silent": true});
expect(core.setOutput).toBeCalledWith('manifestsBundle', path.join('tempDirPath', 'baked-template-12345678.yaml'));
});
test('HelmRenderEngine() - bake manifest using helm', async () => {
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
jest
.spyOn(core, 'getInput')
.mockReturnValueOnce('pathToHelmChart')
.mockReturnValueOnce('releaseName')
jest.spyOn(console, 'log').mockImplementation()
mockStatusCode = 0
stdOutMessage = 'v2.9.1'
process.env['RUNNER_TEMP'] = 'tempDirPath'
jest.spyOn(fs, 'writeFileSync').mockImplementation()
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'setOutput').mockImplementation()
test('HelmRenderEngine() - single additional argument', async () => {
process.env['INPUT_RENDERENGINE'] = 'helm';
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == "helmChart") return 'pathToHelmChart';
if (inputName == "arguments") return 'additionalArguments';
if (inputName == "releaseName") return 'releaseName';
})
jest.spyOn(console, 'log').mockImplementation();
mockStatusCode = 0;
stdOutMessage = 'v2.9.1';
process.env['RUNNER_TEMP'] = 'tempDirPath';
jest.spyOn(fs, 'writeFileSync').mockImplementation();
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'setOutput').mockImplementation();
const execResult = {
stdout: 'test output'
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValue(execResult as utils.ExecResult)
const execResult = {
'stdout': 'test output'
};
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
['dependency', 'update', 'pathToHelmChart'],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
['version', '--template', '{{.Version}}'],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
[
'init',
'--client-only',
'--stable-repo-url',
'https://charts.helm.sh/stable'
],
{silent: true}
)
expect(core.setOutput).toBeCalledWith(
'manifestsBundle',
path.join('tempDirPath', 'baked-template-12345678.yaml')
)
})
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['dependency', 'update', 'pathToHelmChart'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['template', 'additionalArguments', '--name', 'releaseName', 'pathToHelmChart'], { "silent": true });
});
test('HelmRenderEngine() - single additional argument', async () => {
process.env['INPUT_RENDERENGINE'] = 'helm'
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == 'helmChart') return 'pathToHelmChart'
if (inputName == 'arguments') return 'additionalArguments'
if (inputName == 'releaseName') return 'releaseName'
})
jest.spyOn(console, 'log').mockImplementation()
mockStatusCode = 0
stdOutMessage = 'v2.9.1'
process.env['RUNNER_TEMP'] = 'tempDirPath'
jest.spyOn(fs, 'writeFileSync').mockImplementation()
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'setOutput').mockImplementation()
test('HelmRenderEngine() - multiple additional arguments', async () => {
process.env['INPUT_RENDERENGINE'] = 'helm';
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == "helmChart") return 'pathToHelmChart';
if (inputName == "arguments") return 'additional\nArguments';
if (inputName == "releaseName") return 'releaseName';
})
jest.spyOn(console, 'log').mockImplementation();
mockStatusCode = 0;
stdOutMessage = 'v2.9.1';
process.env['RUNNER_TEMP'] = 'tempDirPath';
jest.spyOn(fs, 'writeFileSync').mockImplementation();
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'setOutput').mockImplementation();
const execResult = {
stdout: 'test output'
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValue(execResult as utils.ExecResult)
const execResult = {
'stdout': 'test output'
};
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
['dependency', 'update', 'pathToHelmChart'],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
['version', '--template', '{{.Version}}'],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
[
'template',
'additionalArguments',
'--name',
'releaseName',
'pathToHelmChart'
],
{silent: true}
)
})
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['template', 'additional', 'Arguments', '--name', 'releaseName', 'pathToHelmChart'], { "silent": true });
});
test('HelmRenderEngine() - multiple additional arguments', async () => {
process.env['INPUT_RENDERENGINE'] = 'helm'
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == 'helmChart') return 'pathToHelmChart'
if (inputName == 'arguments') return 'additional\nArguments'
if (inputName == 'releaseName') return 'releaseName'
})
jest.spyOn(console, 'log').mockImplementation()
mockStatusCode = 0
stdOutMessage = 'v2.9.1'
process.env['RUNNER_TEMP'] = 'tempDirPath'
jest.spyOn(fs, 'writeFileSync').mockImplementation()
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'setOutput').mockImplementation()
test('HelmRenderEngine() - no additional arguments', async () => {
process.env['INPUT_RENDERENGINE'] = 'helm';
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == "helmChart") return 'pathToHelmChart';
if (inputName == "arguments") return '';
if (inputName == "releaseName") return 'releaseName';
})
jest.spyOn(console, 'log').mockImplementation();
mockStatusCode = 0;
stdOutMessage = 'v2.9.1';
process.env['RUNNER_TEMP'] = 'tempDirPath';
jest.spyOn(fs, 'writeFileSync').mockImplementation();
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
jest.spyOn(core, 'setOutput').mockImplementation();
const execResult = {
stdout: 'test output'
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValue(execResult as utils.ExecResult)
const execResult = {
'stdout': 'test output'
};
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
['version', '--template', '{{.Version}}'],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
[
'init',
'--client-only',
'--stable-repo-url',
'https://charts.helm.sh/stable'
],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
[
'template',
'additional',
'Arguments',
'--name',
'releaseName',
'pathToHelmChart'
],
{silent: true}
)
})
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], {"silent": true});
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['template', '--name', 'releaseName', 'pathToHelmChart'], { "silent": true });
});
});
test('HelmRenderEngine() - no additional arguments', async () => {
process.env['INPUT_RENDERENGINE'] = 'helm'
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
if (inputName == 'helmChart') return 'pathToHelmChart'
if (inputName == 'arguments') return ''
if (inputName == 'releaseName') return 'releaseName'
})
jest.spyOn(console, 'log').mockImplementation()
mockStatusCode = 0
stdOutMessage = 'v2.9.1'
process.env['RUNNER_TEMP'] = 'tempDirPath'
jest.spyOn(fs, 'writeFileSync').mockImplementation()
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
jest.spyOn(core, 'setOutput').mockImplementation()
const execResult = {
stdout: 'test output'
}
jest
.spyOn(utils, 'execCommand')
.mockResolvedValue(execResult as utils.ExecResult)
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
['version', '--template', '{{.Version}}'],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
[
'init',
'--client-only',
'--stable-repo-url',
'https://charts.helm.sh/stable'
],
{silent: true}
)
expect(utils.execCommand).toBeCalledWith(
'pathToHelm',
['template', '--name', 'releaseName', 'pathToHelmChart'],
{silent: true}
)
})
})

Просмотреть файл

@ -1,250 +1,307 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as core from '@actions/core';
import * as ioUtil from '@actions/io/lib/io-util';
import { ExecOptions } from "@actions/exec/lib/interfaces";
import * as utilities from "./utilities"
import * as path from 'path';
import * as fs from 'fs';
import * as util from 'util';
import { getHelmPath, NameValuePair } from "./helm-util"
import { getKubectlPath } from "./kubectl-util"
import { getKomposePath } from "./kompose-util"
import * as core from '@actions/core'
import * as ioUtil from '@actions/io/lib/io-util'
import {ExecOptions} from '@actions/exec/lib/interfaces'
import * as utilities from './utilities'
import * as path from 'path'
import * as fs from 'fs'
import * as util from 'util'
import {getHelmPath, NameValuePair} from './helm-util'
import {getKubectlPath} from './kubectl-util'
import {getKomposePath} from './kompose-util'
abstract class RenderEngine {
public bake!: (isSilent: boolean) => Promise<any>;
protected getTemplatePath = () => {
const tempDirectory = process.env['RUNNER_TEMP'];
if (!!tempDirectory) {
return path.join(tempDirectory, 'baked-template-' + utilities.getCurrentTime().toString() + '.yaml');
}
else {
throw Error("Unable to create temp directory.");
}
}
public bake!: (isSilent: boolean) => Promise<any>
protected getTemplatePath = () => {
const tempDirectory = process.env['RUNNER_TEMP']
if (!!tempDirectory) {
return path.join(
tempDirectory,
'baked-template-' + utilities.getCurrentTime().toString() + '.yaml'
)
} else {
throw Error('Unable to create temp directory.')
}
}
}
export class HelmRenderEngine extends RenderEngine {
public bake = async (isSilent: boolean): Promise<any> => {
const helmPath = await getHelmPath();
const chartPath = core.getInput('helmChart', { required: true });
public bake = async (isSilent: boolean): Promise<any> => {
const helmPath = await getHelmPath()
const chartPath = core.getInput('helmChart', {required: true})
const options = {
silent: isSilent
} as ExecOptions;
const options = {
silent: isSilent
} as ExecOptions
const dependencyArgs = this.getDependencyArgs(chartPath);
const dependencyArgs = this.getDependencyArgs(chartPath)
console.log("Running helm dependency update command..");
await utilities.execCommand(helmPath, dependencyArgs, options);
console.log('Running helm dependency update command..')
await utilities.execCommand(helmPath, dependencyArgs, options)
console.log("Getting helm version..");
let isV3 = true;
await this.isHelmV3(helmPath).then((result) => { isV3 = result }).catch(() => { isV3 = false });
console.log('Getting helm version..')
let isV3 = true
await this.isHelmV3(helmPath)
.then((result) => {
isV3 = result
})
.catch(() => {
isV3 = false
})
try {
if (!isV3) {
await utilities.execCommand(helmPath, ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], options);
}
} catch (ex) {
core.warning(util.format('Could not run helm init command: ', ex));
}
try {
if (!isV3) {
await utilities.execCommand(
helmPath,
[
'init',
'--client-only',
'--stable-repo-url',
'https://charts.helm.sh/stable'
],
options
)
}
} catch (ex) {
core.warning(util.format('Could not run helm init command: ', ex))
}
console.log("Creating the template argument string..");
const args = await this.getHelmTemplateArgs(chartPath, isV3);
console.log('Creating the template argument string..')
const args = await this.getHelmTemplateArgs(chartPath, isV3)
console.log("Running helm template command..");
const result = await utilities.execCommand(helmPath, args, options)
console.log('Running helm template command..')
const result = await utilities.execCommand(helmPath, args, options)
const pathToBakedManifest = this.getTemplatePath();
fs.writeFileSync(pathToBakedManifest, result.stdout);
core.setOutput('manifestsBundle', pathToBakedManifest);
}
const pathToBakedManifest = this.getTemplatePath()
fs.writeFileSync(pathToBakedManifest, result.stdout)
core.setOutput('manifestsBundle', pathToBakedManifest)
}
private getOverrideValues(overrides: string[]) {
const overrideValues: NameValuePair[] = [];
overrides.forEach(arg => {
const overrideInput = arg.split(':');
const overrideName = overrideInput[0];
const overrideValue = overrideInput.slice(1).join(':');
overrideValues.push({
name: overrideName,
value: overrideValue
} as NameValuePair);
});
private getOverrideValues(overrides: string[]) {
const overrideValues: NameValuePair[] = []
overrides.forEach((arg) => {
const overrideInput = arg.split(':')
const overrideName = overrideInput[0]
const overrideValue = overrideInput.slice(1).join(':')
overrideValues.push({
name: overrideName,
value: overrideValue
} as NameValuePair)
})
return overrideValues;
}
return overrideValues
}
private getDependencyArgs(chartPath: string): string[] {
let args: string[] = [];
args.push('dependency');
args.push('update');
args.push(chartPath);
private getDependencyArgs(chartPath: string): string[] {
let args: string[] = []
args.push('dependency')
args.push('update')
args.push(chartPath)
return args;
}
return args
}
private async getHelmTemplateArgs(chartPath: string, isV3: boolean): Promise<string[]> {
const releaseName = core.getInput('releaseName', { required: false });
let args: string[] = [];
args.push('template');
const templateArgs = await getTemplateArguments(chartPath);
args = args.concat(templateArgs);
private async getHelmTemplateArgs(
chartPath: string,
isV3: boolean
): Promise<string[]> {
const releaseName = core.getInput('releaseName', {required: false})
let args: string[] = []
args.push('template')
const templateArgs = await getTemplateArguments()
args = args.concat(templateArgs)
const namespace = core.getInput('namespace', { required: false });
if (namespace) {
args.push('--namespace');
args.push(namespace);
}
const namespace = core.getInput('namespace', {required: false})
if (namespace) {
args.push('--namespace')
args.push(namespace)
}
if (isV3) {
if (releaseName) {
args.push(releaseName);
}
} else {
if (releaseName) {
args.push('--name');
args.push(releaseName);
}
}
args.push(chartPath);
if (isV3) {
if (releaseName) {
args.push(releaseName)
}
} else {
if (releaseName) {
args.push('--name')
args.push(releaseName)
}
}
args.push(chartPath)
const overrideFilesInput = core.getInput('overrideFiles', { required: false });
if (!!overrideFilesInput) {
core.debug("Adding overrides file inputs");
const overrideFiles = overrideFilesInput.split('\n');
if (overrideFiles.length > 0) {
overrideFiles.forEach(file => {
args.push('-f');
args.push(file);
});
}
}
const overrideFilesInput = core.getInput('overrideFiles', {
required: false
})
if (!!overrideFilesInput) {
core.debug('Adding overrides file inputs')
const overrideFiles = overrideFilesInput.split('\n')
if (overrideFiles.length > 0) {
overrideFiles.forEach((file) => {
args.push('-f')
args.push(file)
})
}
}
const overridesInput = core.getInput('overrides', { required: false });
if (!!overridesInput) {
core.debug("Adding overrides inputs");
const overrides = overridesInput.split('\n');
if (overrides.length > 0) {
const overrideValues = this.getOverrideValues(overrides);
overrideValues.forEach(overrideValue => {
args.push('--set');
args.push(`${overrideValue.name}=${overrideValue.value}`);
});
}
}
return args;
}
const overridesInput = core.getInput('overrides', {required: false})
if (!!overridesInput) {
core.debug('Adding overrides inputs')
const overrides = overridesInput.split('\n')
if (overrides.length > 0) {
const overrideValues = this.getOverrideValues(overrides)
overrideValues.forEach((overrideValue) => {
args.push('--set')
args.push(`${overrideValue.name}=${overrideValue.value}`)
})
}
}
return args
}
private async isHelmV3(path: string) {
let result = await utilities.execCommand(path, ["version", "--template", "{{.Version}}"], { silent: true });
return result.stdout.split('.')[0] === 'v3';
}
private async isHelmV3(path: string) {
let result = await utilities.execCommand(
path,
['version', '--template', '{{.Version}}'],
{silent: true}
)
return result.stdout.split('.')[0] === 'v3'
}
}
export class KomposeRenderEngine extends RenderEngine {
public bake = async (isSilent: boolean): Promise<any> => {
const dockerComposeFilePath = core.getInput('dockerComposeFile', { required: true });
if (!ioUtil.exists(dockerComposeFilePath)) {
throw Error(util.format("Docker compose file path %s does not exist. Please check the path specified", dockerComposeFilePath));
}
public bake = async (isSilent: boolean): Promise<any> => {
const dockerComposeFilePath = core.getInput('dockerComposeFile', {
required: true
})
if (!ioUtil.exists(dockerComposeFilePath)) {
throw Error(
util.format(
'Docker compose file path %s does not exist. Please check the path specified',
dockerComposeFilePath
)
)
}
const options = {
silent: isSilent
} as ExecOptions;
const options = {
silent: isSilent
} as ExecOptions
const komposePath = await getKomposePath();
const pathToBakedManifest = this.getTemplatePath();
core.debug("Running kompose command..");
await utilities.execCommand(komposePath, ['convert', '-f', dockerComposeFilePath, '-o', pathToBakedManifest], options)
core.setOutput('manifestsBundle', pathToBakedManifest);
}
const komposePath = await getKomposePath()
const pathToBakedManifest = this.getTemplatePath()
core.debug('Running kompose command..')
await utilities.execCommand(
komposePath,
['convert', '-f', dockerComposeFilePath, '-o', pathToBakedManifest],
options
)
core.setOutput('manifestsBundle', pathToBakedManifest)
}
}
export class KustomizeRenderEngine extends RenderEngine {
public bake = async (isSilent: boolean) => {
const kubectlPath = await getKubectlPath();
await this.validateKustomize(kubectlPath);
const kustomizationPath = core.getInput('kustomizationPath', { required: true });
if (!ioUtil.exists(kustomizationPath)) {
throw Error(util.format("kustomizationPath %s does not exist. Please check whether file exists or not.", kustomizationPath));
}
public bake = async (isSilent: boolean) => {
const kubectlPath = await getKubectlPath()
await this.validateKustomize(kubectlPath)
const kustomizationPath = core.getInput('kustomizationPath', {
required: true
})
if (!ioUtil.exists(kustomizationPath)) {
throw Error(
util.format(
'kustomizationPath %s does not exist. Please check whether file exists or not.',
kustomizationPath
)
)
}
const options = {
silent: isSilent
} as ExecOptions;
const options = {
silent: isSilent
} as ExecOptions
core.info("Creating the template argument string..");
let args: string[] = ['kustomize', kustomizationPath]
const userargs = await getTemplateArguments(kustomizationPath)
args = args.concat(userargs)
core.info('Creating the template argument string..')
let tempArgs: string[] = ['kustomize', kustomizationPath]
const userargs = await getTemplateArguments()
tempArgs = tempArgs.concat(userargs)
core.debug("Running kubectl kustomize command..");
console.log(`[command] ${kubectlPath} kustomize ${core.getInput('kustomizationPath')}`);
const result = await utilities.execCommand(kubectlPath, args, options);
const pathToBakedManifest = this.getTemplatePath();
fs.writeFileSync(pathToBakedManifest, result.stdout);
core.setOutput('manifestsBundle', pathToBakedManifest);
};
core.debug('Running kubectl kustomize command..')
console.log(
`[command] ${kubectlPath} kustomize ${core.getInput(
'kustomizationPath'
)}`
)
const result = await utilities.execCommand(kubectlPath, tempArgs, options)
const pathToBakedManifest = this.getTemplatePath()
fs.writeFileSync(pathToBakedManifest, result.stdout)
core.setOutput('manifestsBundle', pathToBakedManifest)
}
private async validateKustomize(kubectlPath: string) {
const result = await utilities.execCommand(kubectlPath, ['version', '--client=true', '-o', 'json']);
if (!!result.stdout) {
const clientVersion = JSON.parse(result.stdout).clientVersion;
const versionNumber = `${clientVersion.major}.${clientVersion.minor}`;
if (!clientVersion || parseFloat(versionNumber) < parseFloat(utilities.MIN_KUBECTL_CLIENT_VERSION)) {
throw new Error("kubectl client version equal to v1.14 or higher is required to use kustomize features");
}
}
}
private async validateKustomize(kubectlPath: string) {
const result = await utilities.execCommand(kubectlPath, [
'version',
'--client=true',
'-o',
'json'
])
if (!!result.stdout) {
const clientVersion = JSON.parse(result.stdout).clientVersion
const versionNumber = `${clientVersion.major}.${clientVersion.minor}`
if (
!clientVersion ||
parseFloat(versionNumber) <
parseFloat(utilities.MIN_KUBECTL_CLIENT_VERSION)
) {
throw new Error(
'kubectl client version equal to v1.14 or higher is required to use kustomize features'
)
}
}
}
}
export async function getTemplateArguments(path: string) {
const args: string[] = [];
const additionalArgs = core.getInput('arguments', { required: false })
if (!!additionalArgs) {
const argumentArray = additionalArgs
.split(/[\n,;]+/) // split into each line
.map((manifest) => manifest.trim()) // remove surrounding whitespace
.filter((manifest) => manifest.length > 0); // remove any blanks
if (argumentArray.length > 0) {
argumentArray.forEach(arg => {
args.push(arg);
});
}
}
return args;
export async function getTemplateArguments() {
const args: string[] = []
const additionalArgs = core.getInput('arguments', {required: false})
if (!!additionalArgs) {
const argumentArray = additionalArgs
.split(/[\n,;]+/) // split into each line
.map((manifest) => manifest.trim()) // remove surrounding whitespace
.filter((manifest) => manifest.length > 0) // remove any blanks
if (argumentArray.length > 0) {
argumentArray.forEach((arg) => {
args.push(arg)
})
}
}
return args
}
export async function run() {
const renderType = core.getInput('renderEngine', { required: true });
let renderEngine: RenderEngine;
switch (renderType) {
case 'helm':
case 'helm2':
renderEngine = new HelmRenderEngine();
break;
case 'kompose':
renderEngine = new KomposeRenderEngine();
break;
case 'kustomize':
renderEngine = new KustomizeRenderEngine();
break;
default:
throw Error("Unknown render engine");
}
const renderType = core.getInput('renderEngine', {required: true})
let renderEngine: RenderEngine
switch (renderType) {
case 'helm':
case 'helm2':
renderEngine = new HelmRenderEngine()
break
case 'kompose':
renderEngine = new KomposeRenderEngine()
break
case 'kustomize':
renderEngine = new KustomizeRenderEngine()
break
default:
throw Error('Unknown render engine')
}
let isSilent = core.getInput('silent', { required: false }) === 'true';
let isSilent = core.getInput('silent', {required: false}) === 'true'
try {
await renderEngine.bake(isSilent);
}
catch (err) {
throw Error(util.format("Failed to run bake action. Error: %s", err));
}
try {
await renderEngine.bake(isSilent)
} catch (err) {
throw Error(util.format('Failed to run bake action. Error: %s', err))
}
}
run().catch(core.setFailed);
run().catch(core.setFailed)

Просмотреть файл

@ -1,248 +1,266 @@
import * as os from 'os';
import * as fs from 'fs';
import * as toolCache from '@actions/tool-cache';
import { ExecOptions } from "@actions/exec/lib/interfaces";
import * as core from '@actions/core';
import * as utils from './utilities';
import * as os from 'os'
import * as fs from 'fs'
import * as toolCache from '@actions/tool-cache'
import {ExecOptions} from '@actions/exec/lib/interfaces'
import * as core from '@actions/core'
import * as utils from './utilities'
var mockStatusCode, stdOutMessage, stdErrMessage;
var mockStatusCode, stdOutMessage, stdErrMessage
const mockExecFn = jest.fn().mockImplementation((toolPath, args, options) => {
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage);
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage);
return mockStatusCode;
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage)
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage)
return mockStatusCode
})
jest.mock('@actions/exec/lib/toolrunner', () => {
return {
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
return {
exec: () => mockExecFn(toolPath, args, options)
}
})
}
});
return {
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
return {
exec: () => mockExecFn(toolPath, args, options)
}
})
}
})
describe('Test all functions in utilities file', () => {
test('isEqual() - ', () => {
expect(utils.isEqual('', null)).toBeTruthy();
expect(utils.isEqual('a', 'A')).toBeTruthy();
expect(utils.isEqual(null, 'a')).toBeFalsy();
});
test('isEqual() - ', () => {
expect(utils.isEqual('', null)).toBeTruthy()
expect(utils.isEqual('a', 'A')).toBeTruthy()
expect(utils.isEqual(null, 'a')).toBeFalsy()
})
test('getExecutableExtension() - return .exe when os is Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
test('getExecutableExtension() - return .exe when os is Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
expect(utils.getExecutableExtension()).toBe('.exe');
expect(os.type).toBeCalled();
});
expect(utils.getExecutableExtension()).toBe('.exe')
expect(os.type).toBeCalled()
})
test('getExecutableExtension() - return empty string for non-windows OS', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin');
test('getExecutableExtension() - return empty string for non-windows OS', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin')
expect(utils.getExecutableExtension()).toBe('');
expect(os.type).toBeCalled();
});
expect(utils.getExecutableExtension()).toBe('')
expect(os.type).toBeCalled()
})
test('execCommand() - generate and throw error if non-zero code is returned with empty stderr', async () => {
mockStatusCode = 1;
stdOutMessage = '';
stdErrMessage = '';
test('execCommand() - generate and throw error if non-zero code is returned with empty stderr', async () => {
mockStatusCode = 1
stdOutMessage = ''
stdErrMessage = ''
await expect(utils.execCommand('cd', ['nonEsistingDirectory'])).rejects.toThrow('cd exited with result code 1');
});
await expect(
utils.execCommand('cd', ['nonEsistingDirectory'])
).rejects.toThrow('cd exited with result code 1')
})
test('execCommand() - throw stderr if non zero code is returned', async () => {
mockStatusCode = 1;
stdOutMessage = '';
stdErrMessage = 'Directory doesn\'t exist';
await expect(utils.execCommand('cd', ['nonEsistingDirectory'], {} as ExecOptions)).rejects.toThrow('Directory doesn\'t exist');
});
test('execCommand() - throw stderr if non zero code is returned', async () => {
mockStatusCode = 1
stdOutMessage = ''
stdErrMessage = "Directory doesn't exist"
await expect(
utils.execCommand('cd', ['nonEsistingDirectory'], {} as ExecOptions)
).rejects.toThrow("Directory doesn't exist")
})
test('execCommand() - return ExecOptions type object with stdout if exit code is 0', async () => {
mockStatusCode = 0;
stdOutMessage = 'list of files';
stdErrMessage = '';
expect(await utils.execCommand('ls', [], {} as ExecOptions)).toMatchObject({'stderr': '', 'stdout': 'list of files'});
});
test('execCommand() - return ExecOptions type object with stdout if exit code is 0', async () => {
mockStatusCode = 0
stdOutMessage = 'list of files'
stdErrMessage = ''
expect(
await utils.execCommand('ls', [], {} as ExecOptions)
).toMatchObject({stderr: '', stdout: 'list of files'})
})
test('getDownloadUrl() - return the URL to download helm for Linux_x64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux');
jest.spyOn(os, 'arch').mockReturnValue('x64');
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-amd64.zip'
test('getDownloadUrl() - return the URL to download helm for Linux_x64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValue('x64')
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-amd64.zip'
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl);
expect(os.type).toBeCalled();
expect(os.arch).toBeCalled();
});
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
test('getDownloadUrl() - return the URL to download helm for Linux_arm64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux');
jest.spyOn(os, 'arch').mockReturnValue('arm64');
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-arm64.zip'
test('getDownloadUrl() - return the URL to download helm for Linux_arm64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValue('arm64')
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-arm64.zip'
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl);
expect(os.type).toBeCalled();
expect(os.arch).toBeCalled();
});
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
test('getDownloadUrl() - return the URL to download helm for Darwin', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin');
const helmDarwinUrl = 'https://get.helm.sh/helm-v3.2.1-darwin-amd64.zip'
test('getDownloadUrl() - return the URL to download helm for Darwin', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin')
const helmDarwinUrl = 'https://get.helm.sh/helm-v3.2.1-darwin-amd64.zip'
expect(utils.getDownloadUrl('helm','v3.2.1')).toBe(helmDarwinUrl);
expect(os.type).toBeCalled();
});
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmDarwinUrl)
expect(os.type).toBeCalled()
})
test('getDownloadUrl() - return the URL to download helm for Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
test('getDownloadUrl() - return the URL to download helm for Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
const helmWindowsUrl = 'https://get.helm.sh/helm-v3.2.1-windows-amd64.zip'
expect(utils.getDownloadUrl('helm','v3.2.1')).toBe(helmWindowsUrl);
expect(os.type).toBeCalled();
});
const helmWindowsUrl = 'https://get.helm.sh/helm-v3.2.1-windows-amd64.zip'
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmWindowsUrl)
expect(os.type).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kompose for Linux_x64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux');
jest.spyOn(os, 'arch').mockReturnValue('x64');
const komposelLinuxUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-amd64'
test('getDownloadUrl() - return the URL to download kompose for Linux_x64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValue('x64')
const komposelLinuxUrl =
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-amd64'
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelLinuxUrl);
expect(os.type).toBeCalled();
expect(os.arch).toBeCalled();
});
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposelLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kompose for Linux_arm64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux');
jest.spyOn(os, 'arch').mockReturnValue('arm64');
const komposelLinuxUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-arm64'
test('getDownloadUrl() - return the URL to download kompose for Linux_arm64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValue('arm64')
const komposelLinuxUrl =
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-arm64'
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelLinuxUrl);
expect(os.type).toBeCalled();
expect(os.arch).toBeCalled();
});
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposelLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kompose for Darwin', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin');
const komposelDarwinUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-darwin-amd64'
test('getDownloadUrl() - return the URL to download kompose for Darwin', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin')
const komposelDarwinUrl =
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-darwin-amd64'
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelDarwinUrl);
expect(os.type).toBeCalled();
});
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposelDarwinUrl)
expect(os.type).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kompose for Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
test('getDownloadUrl() - return the URL to download kompose for Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
const komposeWindowsUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe'
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposeWindowsUrl);
expect(os.type).toBeCalled();
});
const komposeWindowsUrl =
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe'
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposeWindowsUrl)
expect(os.type).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kubectl for Linux_x64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux');
jest.spyOn(os, 'arch').mockReturnValue('x64');
const kubectlLinuxUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/amd64/kubectl'
test('getDownloadUrl() - return the URL to download kubectl for Linux_x64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValue('x64')
const kubectlLinuxUrl =
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/amd64/kubectl'
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlLinuxUrl);
expect(os.type).toBeCalled();
expect(os.arch).toBeCalled();
});
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kubectl for Linux_arm64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux');
jest.spyOn(os, 'arch').mockReturnValue('arm64');
const kubectlLinuxUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/arm64/kubectl'
test('getDownloadUrl() - return the URL to download kubectl for Linux_arm64', () => {
jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValue('arm64')
const kubectlLinuxUrl =
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/arm64/kubectl'
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlLinuxUrl);
expect(os.type).toBeCalled();
expect(os.arch).toBeCalled();
});
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kubectl for Darwin', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin');
const kubectlDarwinUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/darwin/amd64/kubectl'
test('getDownloadUrl() - return the URL to download kubectl for Darwin', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin')
const kubectlDarwinUrl =
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/darwin/amd64/kubectl'
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlDarwinUrl);
expect(os.type).toBeCalled();
});
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlDarwinUrl)
expect(os.type).toBeCalled()
})
test('getDownloadUrl() - return the URL to download kubectl for Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
test('getDownloadUrl() - return the URL to download kubectl for Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
const kubectlWindowsUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe'
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlWindowsUrl);
expect(os.type).toBeCalled();
});
const kubectlWindowsUrl =
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe'
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlWindowsUrl)
expect(os.type).toBeCalled()
})
test('getDownloadUrl() - should throw an error if called with incorrect OS type', () => {
jest.spyOn(os, 'type').mockReturnValue('wrong_os')
expect(() => {
utils.getDownloadUrl('kubectl','v1.15.0')
}).toThrow('Unknown OS or render engine type');
expect(os.type).toBeCalled();
});
test('getDownloadUrl() - should throw an error if called with incorrect OS type', () => {
jest.spyOn(os, 'type').mockReturnValue('wrong_os')
expect(() => {
utils.getDownloadUrl('kubectl', 'v1.15.0')
}).toThrow('Unknown OS or render engine type')
expect(os.type).toBeCalled()
})
test('getDownloadUrl() - should throw an error if called with incorrect render engine', () => {
jest.spyOn(os, 'type').mockReturnValue('test_os')
test('getDownloadUrl() - should throw an error if called with incorrect render engine', () => {
jest.spyOn(os, 'type').mockReturnValue('test_os')
expect(() => {
utils.getDownloadUrl('test_render_engine','v1.15.0')
}).toThrow('Unknown OS or render engine type');
expect(os.type).toBeCalled();
});
expect(() => {
utils.getDownloadUrl('test_render_engine', 'v1.15.0')
}).toThrow('Unknown OS or render engine type')
expect(os.type).toBeCalled()
})
test('getStableVerison() - download stable version file for helm, read version and return it', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
const response = JSON.stringify({
'tag_name': 'v4.0.0'
});
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
test('getStableVerison() - download stable version file for helm, read version and return it', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
const response = JSON.stringify({
tag_name: 'v4.0.0'
})
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
expect(await utils.getStableVerison('helm')).toBe('v4.0.0');
expect(toolCache.downloadTool).toBeCalled();
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
});
expect(await utils.getStableVerison('helm')).toBe('v4.0.0')
expect(toolCache.downloadTool).toBeCalled()
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
})
test('getStableVerison() - return default helm version if stable version file is empty', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
const response = JSON.stringify({});
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
test('getStableVerison() - return default helm version if stable version file is empty', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
const response = JSON.stringify({})
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
expect(await utils.getStableVerison('helm')).toBe('v2.14.1');
expect(toolCache.downloadTool).toBeCalled();
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
});
expect(await utils.getStableVerison('helm')).toBe('v2.14.1')
expect(toolCache.downloadTool).toBeCalled()
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
})
test('getStableVerison() - return default helm version if stable version file download fails', async () => {
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Error!!'});
test('getStableVerison() - return default helm version if stable version file download fails', async () => {
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
throw 'Error!!'
})
expect(await utils.getStableVerison('helm')).toBe('v2.14.1');
expect(toolCache.downloadTool).toBeCalled();
});
expect(await utils.getStableVerison('helm')).toBe('v2.14.1')
expect(toolCache.downloadTool).toBeCalled()
})
test('getStableVerison() - return default kubectl v1.15.0 if unable to download file', async () => {
jest.spyOn(toolCache, 'downloadTool').mockRejectedValue('Unable to download.');
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(core, 'warning').mockImplementation();
test('getStableVerison() - return default kubectl v1.15.0 if unable to download file', async () => {
jest
.spyOn(toolCache, 'downloadTool')
.mockRejectedValue('Unable to download.')
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(core, 'warning').mockImplementation()
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0');
expect(toolCache.downloadTool).toBeCalled();
});
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0')
expect(toolCache.downloadTool).toBeCalled()
})
test('getStableVerison() - return default kubectl v1.15.0 if version read is empty', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
jest.spyOn(fs, 'readFileSync').mockReturnValue('');
jest.spyOn(core, 'warning').mockImplementation();
test('getStableVerison() - return default kubectl v1.15.0 if version read is empty', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(fs, 'readFileSync').mockReturnValue('')
jest.spyOn(core, 'warning').mockImplementation()
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0');
expect(toolCache.downloadTool).toBeCalled();
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
});
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0')
expect(toolCache.downloadTool).toBeCalled()
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
})
test('getStableVerison() - download stable kubectl version file, read version and return it', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
jest.spyOn(fs, 'readFileSync').mockReturnValue('v2.14.1');
test('getStableVerison() - download stable kubectl version file, read version and return it', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(fs, 'readFileSync').mockReturnValue('v2.14.1')
expect(await utils.getStableVerison('kubectl')).toBe('v2.14.1');
expect(toolCache.downloadTool).toBeCalled();
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
});
});
expect(await utils.getStableVerison('kubectl')).toBe('v2.14.1')
expect(toolCache.downloadTool).toBeCalled()
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
})
})

Просмотреть файл

@ -1,151 +1,192 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as os from 'os';
import * as fs from 'fs';
import * as util from 'util';
import { ToolRunner } from '@actions/exec/lib/toolrunner';
import { ExecOptions } from "@actions/exec/lib/interfaces";
import * as toolCache from '@actions/tool-cache';
import * as core from '@actions/core';
import * as os from 'os'
import * as fs from 'fs'
import * as util from 'util'
import {ToolRunner} from '@actions/exec/lib/toolrunner'
import {ExecOptions} from '@actions/exec/lib/interfaces'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
export interface ExecResult {
stdout: string;
stderr: string
stdout: string
stderr: string
}
export function getCurrentTime(): number {
return new Date().getTime();
return new Date().getTime()
}
export function isEqual(str1: string, str2: string) {
if (!str1) str1 = "";
if (!str2) str2 = "";
return str1.toLowerCase() === str2.toLowerCase();
if (!str1) str1 = ''
if (!str2) str2 = ''
return str1.toLowerCase() === str2.toLowerCase()
}
export function getExecutableExtension(): string {
if (os.type().match(/^Win/)) {
return '.exe';
}
return '';
if (os.type().match(/^Win/)) {
return '.exe'
}
return ''
}
export async function execCommand(toolPath: string, args: string[], options: ExecOptions = {} as ExecOptions) : Promise<ExecResult> {
const execResult = {
stdout : "",
stderr : ""
} as ExecResult;
export async function execCommand(
toolPath: string,
args: string[],
options: ExecOptions = {} as ExecOptions
): Promise<ExecResult> {
const execResult = {
stdout: '',
stderr: ''
} as ExecResult
options.listeners = {
stdout: (data: Buffer) => {
execResult.stdout += data.toString();
},
stderr: (data: Buffer) => {
execResult.stderr += data.toString();
}
}
options.listeners = {
stdout: (data: Buffer) => {
execResult.stdout += data.toString()
},
stderr: (data: Buffer) => {
execResult.stderr += data.toString()
}
}
let toolRunner = new ToolRunner(toolPath, args, options);
const result = await toolRunner.exec();
if (result != 0) {
if (!!execResult.stderr) {
throw Error(execResult.stderr);
}
else {
throw Error(util.format("%s exited with result code %s", toolPath, result));
}
}
let toolRunner = new ToolRunner(toolPath, args, options)
const result = await toolRunner.exec()
if (result != 0) {
if (!!execResult.stderr) {
throw Error(execResult.stderr)
} else {
throw Error(
util.format('%s exited with result code %s', toolPath, result)
)
}
}
return execResult;
return execResult
}
export async function setCachedToolPath(toolName: string, version: string) {
let cachedToolpath = ''
let downloadPath = ''
const downloadUrl = getDownloadUrl(toolName, version)
try {
downloadPath = await toolCache.downloadTool(downloadUrl)
} catch (exeption) {
throw new Error(
`Failed to download the ${toolName} from ${downloadUrl}. Error: ${exeption}`
)
}
export async function setCachedToolPath(toolName:string, version : string) {
let cachedToolpath = ''
let downloadPath = ''
const downloadUrl = getDownloadUrl(toolName, version);
if (toolName == 'helm') {
fs.chmodSync(downloadPath, '777')
const unzipedHelmPath = await toolCache.extractZip(downloadPath)
cachedToolpath = await toolCache.cacheDir(
unzipedHelmPath,
toolName,
version
)
} else {
cachedToolpath = await toolCache.cacheFile(
downloadPath,
toolName + getExecutableExtension(),
toolName,
version
)
}
try {
downloadPath = await toolCache.downloadTool(downloadUrl);
} catch(exeption) {
throw new Error(`Failed to download the ${toolName} from ${downloadUrl}. Error: ${exeption}`)
}
if(toolName == 'helm') {
fs.chmodSync(downloadPath, '777');
const unzipedHelmPath = await toolCache.extractZip(downloadPath);
cachedToolpath = await toolCache.cacheDir(unzipedHelmPath, toolName, version);
} else {
cachedToolpath = await toolCache.cacheFile(downloadPath, toolName + getExecutableExtension(), toolName, version);
}
return cachedToolpath
return cachedToolpath
}
export function getDownloadUrl(toolName : string, version: string): string {
const system = os.type()
const systemAndArch = system == "Linux" ? `${system}_${os.arch()}` : system;
export function getDownloadUrl(toolName: string, version: string): string {
const system = os.type()
const systemAndArch = system == 'Linux' ? `${system}_${os.arch()}` : system
if (!downloadLinks[systemAndArch] || !downloadLinks[systemAndArch][toolName]) {
throw Error("Unknown OS or render engine type");
}
if (
!downloadLinks[systemAndArch] ||
!downloadLinks[systemAndArch][toolName]
) {
throw Error('Unknown OS or render engine type')
}
return util.format(downloadLinks[systemAndArch][toolName], version)
return util.format(downloadLinks[systemAndArch][toolName], version)
}
export async function getStableVerison(toolName : string){
if(!stableVersionUrls[toolName]){
throw Error("Unable to download. Unknown tool name");
}
export async function getStableVerison(toolName: string) {
if (!stableVersionUrls[toolName]) {
throw Error('Unable to download. Unknown tool name')
}
return toolCache.downloadTool(stableVersionUrls[toolName]).then(downloadPath => {
let response = fs.readFileSync(downloadPath, 'utf8').toString().trim();
if(toolName == 'helm'){
const versionTag = JSON.parse(response);
return versionTag.tag_name ? versionTag.tag_name : defaultStableHelmVersion;
} else {
return response ? response : defaultStableKubectlVersion;
}
}, err => {
core.debug(err);
core.warning(util.format("Failed to read latest %s version from URL %s. Using default stable version %s", toolName, stableVersionUrls[toolName] ,toolName == 'helm' ? defaultStableHelmVersion: defaultStableKubectlVersion));
return toolName == 'helm' ? defaultStableHelmVersion: defaultStableKubectlVersion;
})
return toolCache.downloadTool(stableVersionUrls[toolName]).then(
(downloadPath) => {
let response = fs.readFileSync(downloadPath, 'utf8').toString().trim()
if (toolName == 'helm') {
const versionTag = JSON.parse(response)
return versionTag.tag_name
? versionTag.tag_name
: defaultStableHelmVersion
} else {
return response ? response : defaultStableKubectlVersion
}
},
(err) => {
core.debug(err)
core.warning(
util.format(
'Failed to read latest %s version from URL %s. Using default stable version %s',
toolName,
stableVersionUrls[toolName],
toolName == 'helm'
? defaultStableHelmVersion
: defaultStableKubectlVersion
)
)
return toolName == 'helm'
? defaultStableHelmVersion
: defaultStableKubectlVersion
}
)
}
const defaultStableHelmVersion = 'v2.14.1';
const defaultStableKubectlVersion = 'v1.15.0';
const defaultStableHelmVersion = 'v2.14.1'
const defaultStableKubectlVersion = 'v1.15.0'
const stableVersionUrls = {
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/stable.txt',
'helm': 'https://api.github.com/repos/helm/helm/releases/latest',
kubectl:
'https://storage.googleapis.com/kubernetes-release/release/stable.txt',
helm: 'https://api.github.com/repos/helm/helm/releases/latest'
}
const downloadLinks = {
'Linux_x64': {
'helm' : 'https://get.helm.sh/helm-%s-linux-amd64.zip',
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-amd64',
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubectl'
},
'Linux_arm64': {
'helm' : 'https://get.helm.sh/helm-%s-linux-arm64.zip',
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-arm64',
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/arm64/kubectl'
},
'Darwin' : {
'helm' : 'https://get.helm.sh/helm-%s-darwin-amd64.zip',
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-darwin-amd64',
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/darwin/amd64/kubectl'
},
'Windows_NT' : {
'helm' : 'https://get.helm.sh/helm-%s-windows-amd64.zip',
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-windows-amd64.exe',
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/windows/amd64/kubectl.exe'
}
Linux_x64: {
helm: 'https://get.helm.sh/helm-%s-linux-amd64.zip',
kompose:
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-amd64',
kubectl:
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubectl'
},
Linux_arm64: {
helm: 'https://get.helm.sh/helm-%s-linux-arm64.zip',
kompose:
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-arm64',
kubectl:
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/arm64/kubectl'
},
Darwin: {
helm: 'https://get.helm.sh/helm-%s-darwin-amd64.zip',
kompose:
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-darwin-amd64',
kubectl:
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/darwin/amd64/kubectl'
},
Windows_NT: {
helm: 'https://get.helm.sh/helm-%s-windows-amd64.zip',
kompose:
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-windows-amd64.exe',
kubectl:
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/windows/amd64/kubectl.exe'
}
}
export const LATEST = 'latest';
export const MIN_KUBECTL_CLIENT_VERSION = "1.14"
export const LATEST = 'latest'
export const MIN_KUBECTL_CLIENT_VERSION = '1.14'

Просмотреть файл

@ -1,35 +1,35 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: acs-helloworld-{{.Release.Name}}
namespace: {{ .Release.Namespace }}
name: acs-helloworld-{{.Release.Name}}
namespace: {{.Release.Namespace}}
spec:
replicas: 1
selector:
matchLabels:
app: acs-helloworld-{{.Release.Name}}
template:
metadata:
labels:
app: acs-helloworld-{{.Release.Name}}
spec:
containers:
- name: acs-helloworld-{{.Release.Name}}
image: neilpeterson/aks-helloworld:v1
ports:
- containerPort: 80
env:
- name: TITLE
value: {{ .Values.title }}
replicas: 1
selector:
matchLabels:
app: acs-helloworld-{{.Release.Name}}
template:
metadata:
labels:
app: acs-helloworld-{{.Release.Name}}
spec:
containers:
- name: acs-helloworld-{{.Release.Name}}
image: neilpeterson/aks-helloworld:v1
ports:
- containerPort: 80
env:
- name: TITLE
value: {{.Values.title}}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.serviceName }}
namespace: {{ .Release.Namespace }}
name: {{.Values.serviceName}}
namespace: {{.Release.Namespace}}
spec:
type: {{ .Values.serviceType }}
ports:
- port: 80
selector:
app: acs-helloworld-{{.Release.Name}}
type: {{.Values.serviceType}}
ports:
- port: 80
selector:
app: acs-helloworld-{{.Release.Name}}

Просмотреть файл

@ -1,5 +1,5 @@
# UI controll
title: "Welcome to Azure Kubernetes Service (AKS)"
title: 'Welcome to Azure Kubernetes Service (AKS)'
# Service controlls
serviceName: aks-helloworld

Просмотреть файл

@ -1,24 +1,23 @@
version: "2"
version: '2'
services:
redis-master:
image: k8s.gcr.io/redis:e2e
ports:
- '6379'
redis-master:
image: k8s.gcr.io/redis:e2e
ports:
- "6379"
redis-slave:
image: gcr.io/google_samples/gb-redisslave:v1
ports:
- '6379'
environment:
- GET_HOSTS_FROM=dns
redis-slave:
image: gcr.io/google_samples/gb-redisslave:v1
ports:
- "6379"
environment:
- GET_HOSTS_FROM=dns
frontend:
image: gcr.io/google-samples/gb-frontend:v4
ports:
- "80:80"
environment:
- GET_HOSTS_FROM=dns
labels:
kompose.service.type: LoadBalancer
frontend:
image: gcr.io/google-samples/gb-frontend:v4
ports:
- '80:80'
environment:
- GET_HOSTS_FROM=dns
labels:
kompose.service.type: LoadBalancer

Просмотреть файл

@ -1,19 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
name: deploy
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
foo: bar
spec:
containers:
- name: nginx
image: nginx
args:
- arg1
- arg2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
foo: bar
spec:
containers:
- name: nginx
image: nginx
args:
- arg1
- arg2

Просмотреть файл

@ -1,2 +1,2 @@
resources:
- deployments.yaml
- deployments.yaml

Просмотреть файл

@ -1,63 +1,63 @@
{
"compilerOptions": {
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./lib", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
"compilerOptions": {
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./lib" /* Redirect output structure to the directory. */,
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
// "strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Strict Type-Checking Options */
// "strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
// "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
// "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
},
"exclude": ["node_modules", "**/*.test.ts"]
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
},
"exclude": ["node_modules", "**/*.test.ts"]
}