Compare commits

..

2 Commits

Author SHA1 Message Date
github-actions[bot] 17f5181337 v3 new release (#192)
* Make pulling of images switchable (#178)

* Make namespace annotation switchable (#177)

* Bump tmpl from 1.0.4 to 1.0.5 (#152)

Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ansi-regex from 5.0.0 to 5.0.1 (#166)

Bumps [ansi-regex](https://github.com/chalk/ansi-regex) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/chalk/ansi-regex/releases)
- [Commits](https://github.com/chalk/ansi-regex/compare/v5.0.0...v5.0.1)

---
updated-dependencies:
- dependency-name: ansi-regex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump minimist from 1.2.5 to 1.2.6 (#175)

Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add directory functionality (#181)

* Modifying README to include instructions/examples for directory functionality (#183)

* Added some tests, not sure what else to try but gonna think of more examples

* forgot some files

* reverted package-lock.json

* Added empty dir test

* Cleaned up some extra spaces

* Add node modules and compiled JavaScript from main

* forgot to actually include functionality

* removed unnecessary files

* Update .gitignore

* Update .gitignore

* Update .gitignore

* thx david

* renamed searchFilesRec

* integrations test fix

* added examples to README

* added note about depth

* added additional note

* removed ticks

* changed version string

Co-authored-by: Jaiveer Katariya <jaiveerkatariya@Jaiveers-MacBook-Pro.local>
Co-authored-by: Oliver King <oking3@uncc.edu>

* Remove kubectl version example (#188)

* prefix for annotations (#191)

* Add node modules and compiled JavaScript from main

Co-authored-by: Jan Röhrich <roehrijn@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jaiveer Katariya <35347859+jaiveerk@users.noreply.github.com>
Co-authored-by: Jaiveer Katariya <jaiveerkatariya@Jaiveers-MacBook-Pro.local>
Co-authored-by: Oliver King <oking3@uncc.edu>
Co-authored-by: David Gamero <david340804@gmail.com>
2022-06-08 14:02:15 -04:00
github-actions[bot] e3c97bfc20 v3 new release (#182)
* Make pulling of images switchable (#178)

* Make namespace annotation switchable (#177)

* Bump tmpl from 1.0.4 to 1.0.5 (#152)

Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ansi-regex from 5.0.0 to 5.0.1 (#166)

Bumps [ansi-regex](https://github.com/chalk/ansi-regex) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/chalk/ansi-regex/releases)
- [Commits](https://github.com/chalk/ansi-regex/compare/v5.0.0...v5.0.1)

---
updated-dependencies:
- dependency-name: ansi-regex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump minimist from 1.2.5 to 1.2.6 (#175)

Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add directory functionality (#181)

* Add node modules and compiled JavaScript from main

Co-authored-by: Jan Röhrich <roehrijn@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jaiveer Katariya <35347859+jaiveerk@users.noreply.github.com>
Co-authored-by: Oliver King <oking3@uncc.edu>
2022-04-12 13:22:09 -04:00
34 changed files with 17395 additions and 17076 deletions
+6 -2
View File
@@ -21,11 +21,15 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Building latest changes - name: Install dependencies
run: | run: |
rm -rf node_modules/ rm -rf node_modules/
npm install npm install
npm run build
- name: Install ncc
run: npm i -g @vercel/ncc
- name: Build
run: ncc build src/run.ts -o lib
- name: Set name of ns - name: Set name of ns
run: echo "::set-output name=name::$(echo `date +%Y%m%d%H%M%S`)" run: echo "::set-output name=name::$(echo `date +%Y%m%d%H%M%S`)"
+24 -14
View File
@@ -42,7 +42,7 @@ Following are the key capabilities of this action:
</tr> </tr>
<tr> <tr>
<td>manifests </br></br>(Required)</td> <td>manifests </br></br>(Required)</td>
<td>Path to the manifest files to be used for deployment</td> <td>Path to the manifest files to be used for deployment. These can also be directories containing manifest files, in which case, all manifest files in the referenced directory at every depth will be deployed. Files not ending in .yml or .yaml will be ignored.</td>
</tr> </tr>
<tr> <tr>
<td>namespace </br></br>(Optional) <td>namespace </br></br>(Optional)
@@ -57,6 +57,10 @@ Following are the key capabilities of this action:
<tr> <tr>
<td>imagepullsecrets </br></br>(Optional)</td> <td>imagepullsecrets </br></br>(Optional)</td>
<td>Multiline input where each line contains the name of a docker-registry secret that has already been setup within the cluster. Each of these secret names are added under imagePullSecrets field for the workloads found in the input manifest files</td> <td>Multiline input where each line contains the name of a docker-registry secret that has already been setup within the cluster. Each of these secret names are added under imagePullSecrets field for the workloads found in the input manifest files</td>
</tr>
<tr>
<td>pull-images</br></br>(Optional)</td>
<td>Acceptable values: true/false</br>Default value: true</br>Switch whether to pull the images from the registry before deployment to find out Dockerfile's path in order to add it to the annotations</td>
</tr> </tr>
<tr> <tr>
<td>strategy </br></br>(Optional)</td> <td>strategy </br></br>(Optional)</td>
@@ -90,6 +94,10 @@ Following are the key capabilities of this action:
<td>force </br></br>(Optional)</td> <td>force </br></br>(Optional)</td>
<td>Deploy when a previous deployment already exists. If true then '--force' argument is added to the apply command. Using '--force' argument is not recommended in production.</td> <td>Deploy when a previous deployment already exists. If true then '--force' argument is added to the apply command. Using '--force' argument is not recommended in production.</td>
</tr> </tr>
<tr>
<td>annotate-namespace</br></br>(Optional)</td>
<td>Acceptable values: true/false</br>Default value: true</br>Switch whether to annotate the namespace resources object or not</td>
</tr>
</table> </table>
## Usage Examples ## Usage Examples
@@ -97,23 +105,21 @@ Following are the key capabilities of this action:
### Basic deployment (without any deployment strategy) ### Basic deployment (without any deployment strategy)
```yaml ```yaml
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
namespace: "myapp" namespace: "myapp"
manifests: | manifests: |
deployment.yaml dir/manifestsDirectory
service.yaml
images: "contoso.azurecr.io/myapp:${{ event.run_id }}" images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
imagepullsecrets: | imagepullsecrets: |
image-pull-secret1 image-pull-secret1
image-pull-secret2 image-pull-secret2
kubectl-version: "latest"
``` ```
### Canary deployment without service mesh ### Canary deployment without service mesh
```yaml ```yaml
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
namespace: "myapp" namespace: "myapp"
images: "contoso.azurecr.io/myapp:${{ event.run_id }}" images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
@@ -123,6 +129,7 @@ Following are the key capabilities of this action:
manifests: | manifests: |
deployment.yaml deployment.yaml
service.yaml service.yaml
dir/manifestsDirectory
strategy: canary strategy: canary
action: deploy action: deploy
percentage: 20 percentage: 20
@@ -131,7 +138,7 @@ Following are the key capabilities of this action:
To promote/reject the canary created by the above snippet, the following YAML snippet could be used: To promote/reject the canary created by the above snippet, the following YAML snippet could be used:
```yaml ```yaml
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
namespace: "myapp" namespace: "myapp"
images: "contoso.azurecr.io/myapp:${{ event.run_id }}" images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
@@ -141,6 +148,7 @@ To promote/reject the canary created by the above snippet, the following YAML sn
manifests: | manifests: |
deployment.yaml deployment.yaml
service.yaml service.yaml
dir/manifestsDirectory
strategy: canary strategy: canary
action: promote # substitute reject if you want to reject action: promote # substitute reject if you want to reject
``` ```
@@ -148,7 +156,7 @@ To promote/reject the canary created by the above snippet, the following YAML sn
### Canary deployment based on Service Mesh Interface ### Canary deployment based on Service Mesh Interface
```yaml ```yaml
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
namespace: "myapp" namespace: "myapp"
images: "contoso.azurecr.io/myapp:${{ event.run_id }}" images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
@@ -158,6 +166,7 @@ To promote/reject the canary created by the above snippet, the following YAML sn
manifests: | manifests: |
deployment.yaml deployment.yaml
service.yaml service.yaml
dir/manifestsDirectory
strategy: canary strategy: canary
action: deploy action: deploy
traffic-split-method: smi traffic-split-method: smi
@@ -168,7 +177,7 @@ To promote/reject the canary created by the above snippet, the following YAML sn
To promote/reject the canary created by the above snippet, the following YAML snippet could be used: To promote/reject the canary created by the above snippet, the following YAML snippet could be used:
```yaml ```yaml
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
namespace: "myapp" namespace: "myapp"
images: "contoso.azurecr.io/myapp:${{ event.run_id }} " images: "contoso.azurecr.io/myapp:${{ event.run_id }} "
@@ -178,6 +187,7 @@ To promote/reject the canary created by the above snippet, the following YAML sn
manifests: | manifests: |
deployment.yaml deployment.yaml
service.yaml service.yaml
dir/manifestsDirectory
strategy: canary strategy: canary
traffic-split-method: smi traffic-split-method: smi
action: reject # substitute reject if you want to reject action: reject # substitute reject if you want to reject
@@ -186,7 +196,7 @@ To promote/reject the canary created by the above snippet, the following YAML sn
### Blue-Green deployment with different route methods ### Blue-Green deployment with different route methods
```yaml ```yaml
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
namespace: "myapp" namespace: "myapp"
images: "contoso.azurecr.io/myapp:${{ event.run_id }}" images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
@@ -206,7 +216,7 @@ To promote/reject the canary created by the above snippet, the following YAML sn
To promote/reject the green workload created by the above snippet, the following YAML snippet could be used: To promote/reject the green workload created by the above snippet, the following YAML snippet could be used:
```yaml ```yaml
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
namespace: "myapp" namespace: "myapp"
images: "contoso.azurecr.io/myapp:${{ event.run_id }}" images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
@@ -216,7 +226,7 @@ To promote/reject the green workload created by the above snippet, the following
manifests: | manifests: |
deployment.yaml deployment.yaml
service.yaml service.yaml
ingress-yml ingress.yml
strategy: blue-green strategy: blue-green
route-method: ingress # should be the same as the value when action was deploy route-method: ingress # should be the same as the value when action was deploy
action: promote # substitute reject if you want to reject action: promote # substitute reject if you want to reject
@@ -263,7 +273,7 @@ jobs:
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }} container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
secret-name: demo-k8s-secret secret-name: demo-k8s-secret
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
action: deploy action: deploy
manifests: | manifests: |
@@ -309,7 +319,7 @@ jobs:
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }} container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
secret-name: demo-k8s-secret secret-name: demo-k8s-secret
- uses: Azure/k8s-deploy@v1.4 - uses: Azure/k8s-deploy@v3.1
with: with:
action: deploy action: deploy
manifests: | manifests: |
+8
View File
@@ -15,6 +15,10 @@ inputs:
imagepullsecrets: imagepullsecrets:
description: "Name of a docker-registry secret that has already been set up within the cluster. Each of these secret names are added under imagePullSecrets field for the workloads found in the input manifest files" description: "Name of a docker-registry secret that has already been set up within the cluster. Each of these secret names are added under imagePullSecrets field for the workloads found in the input manifest files"
required: false required: false
pull-images:
description: "Switch whether to pull the images from the registry before deployment to find out Dockerfile's path in order to add it to the annotations"
required: false
default: true
strategy: strategy:
description: "Deployment strategy to be used. Allowed values are none, canary and blue-green" description: "Deployment strategy to be used. Allowed values are none, canary and blue-green"
required: false required: false
@@ -51,6 +55,10 @@ inputs:
description: "Github token" description: "Github token"
default: ${{ github.token }} default: ${{ github.token }}
required: true required: true
annotate-namespace:
description: "Annotate the target namespace"
required: false
default: true
branding: branding:
color: "green" color: "green"
+71 -14
View File
@@ -18192,6 +18192,7 @@ const promote_1 = __nccwpck_require__(3604);
const reject_1 = __nccwpck_require__(7530); const reject_1 = __nccwpck_require__(7530);
const action_1 = __nccwpck_require__(2868); const action_1 = __nccwpck_require__(2868);
const deploymentStrategy_1 = __nccwpck_require__(7023); const deploymentStrategy_1 = __nccwpck_require__(7023);
const fileUtils_1 = __nccwpck_require__(7446);
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
// verify kubeconfig is set // verify kubeconfig is set
@@ -18205,6 +18206,7 @@ function run() {
.split(/[\n,;]+/) // split into each individual manifest .split(/[\n,;]+/) // split into each individual manifest
.map((manifest) => manifest.trim()) // remove surrounding whitespace .map((manifest) => manifest.trim()) // remove surrounding whitespace
.filter((manifest) => manifest.length > 0); // remove any blanks .filter((manifest) => manifest.length > 0); // remove any blanks
const fullManifestFilePaths = fileUtils_1.getFilesFromDirectories(manifestFilePaths);
// create kubectl // create kubectl
const kubectlPath = yield kubectl_1.getKubectlPath(); const kubectlPath = yield kubectl_1.getKubectlPath();
const namespace = core.getInput("namespace") || "default"; const namespace = core.getInput("namespace") || "default";
@@ -18212,15 +18214,15 @@ function run() {
// run action // run action
switch (action) { switch (action) {
case action_1.Action.DEPLOY: { case action_1.Action.DEPLOY: {
yield deploy_1.deploy(kubectl, manifestFilePaths, strategy); yield deploy_1.deploy(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
case action_1.Action.PROMOTE: { case action_1.Action.PROMOTE: {
yield promote_1.promote(kubectl, manifestFilePaths, strategy); yield promote_1.promote(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
case action_1.Action.REJECT: { case action_1.Action.REJECT: {
yield reject_1.reject(kubectl, manifestFilePaths, strategy); yield reject_1.reject(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
default: { default: {
@@ -19583,7 +19585,10 @@ function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey
const namespace = core.getInput("namespace") || "default"; const namespace = core.getInput("namespace") || "default";
const lastSuccessSha = yield kubectlUtils_1.getLastSuccessfulRunSha(kubectl, namespace, annotationKey); const lastSuccessSha = yield kubectlUtils_1.getLastSuccessfulRunSha(kubectl, namespace, annotationKey);
const annotationKeyValStr = `${annotationKey}=${workflowAnnotationUtils_1.getWorkflowAnnotations(lastSuccessSha, workflowFilePath, deploymentConfig)}`; const annotationKeyValStr = `${annotationKey}=${workflowAnnotationUtils_1.getWorkflowAnnotations(lastSuccessSha, workflowFilePath, deploymentConfig)}`;
annotateResults.push(yield kubectl.annotate("namespace", namespace, annotationKeyValStr)); const annotateNamespace = !(core.getInput("annotate-namespace").toLowerCase() === "false");
if (annotateNamespace) {
annotateResults.push(yield kubectl.annotate("namespace", namespace, annotationKeyValStr));
}
annotateResults.push(yield kubectl.annotateFiles(files, annotationKeyValStr)); annotateResults.push(yield kubectl.annotateFiles(files, annotationKeyValStr));
for (const resource of resourceTypes) { for (const resource of resourceTypes) {
if (resource.type.toLowerCase() !== if (resource.type.toLowerCase() !==
@@ -20082,13 +20087,16 @@ function getDeploymentConfig() {
} }
const imageNames = core.getInput("images").split("\n") || []; const imageNames = core.getInput("images").split("\n") || [];
const imageDockerfilePathMap = {}; const imageDockerfilePathMap = {};
//Fetching from image label if available const pullImages = !(core.getInput("pull-images").toLowerCase() === "false");
for (const image of imageNames) { if (pullImages) {
try { //Fetching from image label if available
imageDockerfilePathMap[image] = yield getDockerfilePath(image); for (const image of imageNames) {
} try {
catch (ex) { imageDockerfilePathMap[image] = yield getDockerfilePath(image);
core.warning(`Failed to get dockerfile path for image ${image.toString()}: ${ex} `); }
catch (ex) {
core.warning(`Failed to get dockerfile path for image ${image.toString()}: ${ex} `);
}
} }
} }
return Promise.resolve({ return Promise.resolve({
@@ -20135,7 +20143,7 @@ exports.checkDockerPath = checkDockerPath;
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.writeManifestToFile = exports.writeObjectsToFile = exports.getTempDirectory = void 0; exports.getFilesFromDirectories = exports.writeManifestToFile = exports.writeObjectsToFile = exports.getTempDirectory = void 0;
const fs = __nccwpck_require__(7147); const fs = __nccwpck_require__(7147);
const path = __nccwpck_require__(1017); const path = __nccwpck_require__(1017);
const core = __nccwpck_require__(6024); const core = __nccwpck_require__(6024);
@@ -20186,6 +20194,46 @@ function getManifestFileName(kind, name) {
const tempDirectory = getTempDirectory(); const tempDirectory = getTempDirectory();
return path.join(tempDirectory, path.basename(filePath)); return path.join(tempDirectory, path.basename(filePath));
} }
function getFilesFromDirectories(filePaths) {
const fullPathSet = new Set();
filePaths.forEach((fileName => {
try {
if (fs.lstatSync(fileName).isDirectory()) {
recurisveManifestGetter(fileName).forEach((file) => { fullPathSet.add(file); });
}
else if (getFileExtension(fileName) === "yml" || getFileExtension(fileName) === "yaml") {
fullPathSet.add(fileName);
}
else {
core.debug(`Detected non-manifest file, ${fileName}, continuing... `);
}
}
catch (ex) {
throw Error(`Exception occurred while reading the file ${fileName}: ${ex}`);
}
}));
return Array.from(fullPathSet);
}
exports.getFilesFromDirectories = getFilesFromDirectories;
function recurisveManifestGetter(dirName) {
const toRet = [];
fs.readdirSync(dirName).forEach((fileName) => {
const fnwd = path.join(dirName, fileName);
if (fs.lstatSync(fnwd).isDirectory()) {
toRet.push(...recurisveManifestGetter(fnwd));
}
else if (getFileExtension(fileName) === "yml" || getFileExtension(fileName) === "yaml") {
toRet.push(path.join(dirName, fileName));
}
else {
core.debug(`Detected non-manifest file, ${fileName}, continuing... `);
}
});
return toRet;
}
function getFileExtension(fileName) {
return fileName.slice((fileName.lastIndexOf(".") - 1 >>> 0) + 2);
}
/***/ }), /***/ }),
@@ -20931,7 +20979,15 @@ exports.getTrafficSplitAPIVersion = getTrafficSplitAPIVersion;
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getWorkflowAnnotationKeyLabel = exports.getWorkflowAnnotations = void 0; exports.getWorkflowAnnotationKeyLabel = exports.getWorkflowAnnotations = exports.prefixObjectKeys = void 0;
const ANNOTATION_PREFIX = "actions.github.com/";
function prefixObjectKeys(obj, prefix) {
return Object.keys(obj).reduce((newObj, key) => {
newObj[prefix + key] = obj[key];
return newObj;
}, {});
}
exports.prefixObjectKeys = prefixObjectKeys;
function getWorkflowAnnotations(lastSuccessRunSha, workflowFilePath, deploymentConfig) { function getWorkflowAnnotations(lastSuccessRunSha, workflowFilePath, deploymentConfig) {
const annotationObject = { const annotationObject = {
run: process.env.GITHUB_RUN_ID, run: process.env.GITHUB_RUN_ID,
@@ -20950,7 +21006,8 @@ function getWorkflowAnnotations(lastSuccessRunSha, workflowFilePath, deploymentC
helmChartPaths: deploymentConfig.helmChartFilePaths, helmChartPaths: deploymentConfig.helmChartFilePaths,
provider: "GitHub", provider: "GitHub",
}; };
return JSON.stringify(annotationObject); const prefixedAnnotationObject = prefixObjectKeys(annotationObject, ANNOTATION_PREFIX);
return JSON.stringify(prefixedAnnotationObject);
} }
exports.getWorkflowAnnotations = getWorkflowAnnotations; exports.getWorkflowAnnotations = getWorkflowAnnotations;
function getWorkflowAnnotationKeyLabel(workflowFilePath) { function getWorkflowAnnotationKeyLabel(workflowFilePath) {
+6075 -6075
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2,7 +2,7 @@
module.exports = ({onlyFirst = false} = {}) => { module.exports = ({onlyFirst = false} = {}) => {
const pattern = [ const pattern = [
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))' '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
].join('|'); ].join('|');
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "ansi-regex", "name": "ansi-regex",
"version": "5.0.0", "version": "5.0.1",
"description": "Regular expression for matching ANSI escape codes", "description": "Regular expression for matching ANSI escape codes",
"license": "MIT", "license": "MIT",
"repository": "chalk/ansi-regex", "repository": "chalk/ansi-regex",
+1 -1
View File
@@ -1,4 +1,4 @@
# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex) # ansi-regex
> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) > Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
+6 -2
View File
@@ -70,7 +70,7 @@ module.exports = function (args, opts) {
var o = obj; var o = obj;
for (var i = 0; i < keys.length-1; i++) { for (var i = 0; i < keys.length-1; i++) {
var key = keys[i]; var key = keys[i];
if (key === '__proto__') return; if (isConstructorOrProto(o, key)) return;
if (o[key] === undefined) o[key] = {}; if (o[key] === undefined) o[key] = {};
if (o[key] === Object.prototype || o[key] === Number.prototype if (o[key] === Object.prototype || o[key] === Number.prototype
|| o[key] === String.prototype) o[key] = {}; || o[key] === String.prototype) o[key] = {};
@@ -79,7 +79,7 @@ module.exports = function (args, opts) {
} }
var key = keys[keys.length - 1]; var key = keys[keys.length - 1];
if (key === '__proto__') return; if (isConstructorOrProto(o, key)) return;
if (o === Object.prototype || o === Number.prototype if (o === Object.prototype || o === Number.prototype
|| o === String.prototype) o = {}; || o === String.prototype) o = {};
if (o === Array.prototype) o = []; if (o === Array.prototype) o = [];
@@ -243,3 +243,7 @@ function isNumber (x) {
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
} }
function isConstructorOrProto (obj, key) {
return key === 'constructor' && typeof obj[key] === 'function' || key === '__proto__';
}
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "minimist", "name": "minimist",
"version": "1.2.5", "version": "1.2.6",
"description": "parse argument options", "description": "parse argument options",
"main": "index.js", "main": "index.js",
"devDependencies": { "devDependencies": {
+4 -1
View File
@@ -34,7 +34,10 @@ $ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
Previous versions had a prototype pollution bug that could cause privilege Previous versions had a prototype pollution bug that could cause privilege
escalation in some circumstances when handling untrusted user input. escalation in some circumstances when handling untrusted user input.
Please use version 1.2.3 or later: https://snyk.io/vuln/SNYK-JS-MINIMIST-559764 Please use version 1.2.6 or later:
* https://security.snyk.io/vuln/SNYK-JS-MINIMIST-2429795 (version <=1.2.5)
* https://snyk.io/vuln/SNYK-JS-MINIMIST-559764 (version <=1.2.3)
# methods # methods
+16
View File
@@ -42,3 +42,19 @@ test('proto pollution (constructor)', function (t) {
t.equal(argv.y, undefined); t.equal(argv.y, undefined);
t.end(); t.end();
}); });
test('proto pollution (constructor function)', function (t) {
var argv = parse(['--_.concat.constructor.prototype.y', '123']);
function fnToBeTested() {}
t.equal(fnToBeTested.y, undefined);
t.equal(argv.y, undefined);
t.end();
});
// powered by snyk - https://github.com/backstage/backstage/issues/10343
test('proto pollution (constructor function) snyk', function (t) {
var argv = parse('--_.constructor.constructor.prototype.foo bar'.split(' '));
t.equal((function(){}).foo, undefined);
t.equal(argv.y, undefined);
t.end();
})
-3
View File
@@ -1,3 +0,0 @@
language: node_js
node_js:
- 0.6
+1 -1
View File
@@ -1,4 +1,4 @@
var INTERPOLATE = /{([\s\S]+?)}/g var INTERPOLATE = /{([^{]+?)}/g
module.exports = function(str, data) { module.exports = function(str, data) {
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
+6 -4
View File
@@ -1,17 +1,19 @@
{ {
"name": "tmpl", "name": "tmpl",
"description": "JavaScript micro templates.", "description": "JavaScript micro templates.",
"version": "1.0.4", "version": "1.0.5",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"homepage": "https://github.com/nshah/nodejs-tmpl", "homepage": "https://github.com/daaku/nodejs-tmpl",
"author": "Naitik Shah <n@daaku.org>", "author": "Naitik Shah <n@daaku.org>",
"main": "lib/tmpl", "main": "lib/tmpl",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/daaku/nodejs-tmpl" "url": "https://github.com/daaku/nodejs-tmpl"
}, },
"scripts": { "test": "NODE_PATH=./lib mocha --ui exports" }, "scripts": {
"test": "NODE_PATH=./lib mocha --ui exports"
},
"devDependencies": { "devDependencies": {
"mocha": "0.12.x" "mocha": "^9.1.1"
} }
} }
+10940 -10940
View File
File diff suppressed because it is too large Load Diff
+6 -4
View File
@@ -5,6 +5,7 @@ import { promote } from "./actions/promote";
import { reject } from "./actions/reject"; import { reject } from "./actions/reject";
import { Action, parseAction } from "./types/action"; import { Action, parseAction } from "./types/action";
import { parseDeploymentStrategy } from "./types/deploymentStrategy"; import { parseDeploymentStrategy } from "./types/deploymentStrategy";
import { getFilesFromDirectories } from "./utilities/fileUtils";
export async function run() { export async function run() {
// verify kubeconfig is set // verify kubeconfig is set
@@ -23,7 +24,8 @@ export async function run() {
.split(/[\n,;]+/) // split into each individual manifest .split(/[\n,;]+/) // split into each individual manifest
.map((manifest) => manifest.trim()) // remove surrounding whitespace .map((manifest) => manifest.trim()) // remove surrounding whitespace
.filter((manifest) => manifest.length > 0); // remove any blanks .filter((manifest) => manifest.length > 0); // remove any blanks
const fullManifestFilePaths = getFilesFromDirectories(manifestFilePaths)
// create kubectl // create kubectl
const kubectlPath = await getKubectlPath(); const kubectlPath = await getKubectlPath();
const namespace = core.getInput("namespace") || "default"; const namespace = core.getInput("namespace") || "default";
@@ -32,15 +34,15 @@ export async function run() {
// run action // run action
switch (action) { switch (action) {
case Action.DEPLOY: { case Action.DEPLOY: {
await deploy(kubectl, manifestFilePaths, strategy); await deploy(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
case Action.PROMOTE: { case Action.PROMOTE: {
await promote(kubectl, manifestFilePaths, strategy); await promote(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
case Action.REJECT: { case Action.REJECT: {
await reject(kubectl, manifestFilePaths, strategy); await reject(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
default: { default: {
+7 -3
View File
@@ -173,9 +173,13 @@ async function annotateResources(
workflowFilePath, workflowFilePath,
deploymentConfig deploymentConfig
)}`; )}`;
annotateResults.push(
await kubectl.annotate("namespace", namespace, annotationKeyValStr) const annotateNamespace = !(core.getInput("annotate-namespace").toLowerCase() === "false");
); if (annotateNamespace) {
annotateResults.push(
await kubectl.annotate("namespace", namespace, annotationKeyValStr)
);
}
annotateResults.push(await kubectl.annotateFiles(files, annotationKeyValStr)); annotateResults.push(await kubectl.annotateFiles(files, annotationKeyValStr));
for (const resource of resourceTypes) { for (const resource of resourceTypes) {
+11 -8
View File
@@ -26,14 +26,17 @@ export async function getDeploymentConfig(): Promise<DeploymentConfig> {
const imageNames = core.getInput("images").split("\n") || []; const imageNames = core.getInput("images").split("\n") || [];
const imageDockerfilePathMap: { [id: string]: string } = {}; const imageDockerfilePathMap: { [id: string]: string } = {};
//Fetching from image label if available const pullImages = !(core.getInput("pull-images").toLowerCase() === "false");
for (const image of imageNames) { if (pullImages) {
try { //Fetching from image label if available
imageDockerfilePathMap[image] = await getDockerfilePath(image); for (const image of imageNames) {
} catch (ex) { try {
core.warning( imageDockerfilePathMap[image] = await getDockerfilePath(image);
`Failed to get dockerfile path for image ${image.toString()}: ${ex} ` } catch (ex) {
); core.warning(
`Failed to get dockerfile path for image ${image.toString()}: ${ex} `
);
}
} }
} }
+49
View File
@@ -0,0 +1,49 @@
import {
getFilesFromDirectories
} from "./fileUtils";
import * as path from "path";
describe("File utils", () => {
it("detects files in nested directories and ignores non-manifest files and empty dirs", () => {
const testPath = path.join("test", "unit", "manifests")
const testSearch: string[] = getFilesFromDirectories([testPath])
const expectedManifests =
[
"test/unit/manifests/manifest_test_dir/another_layer/deep-ingress.yaml",
"test/unit/manifests/manifest_test_dir/another_layer/deep-service.yaml",
"test/unit/manifests/manifest_test_dir/nested-test-service.yaml",
"test/unit/manifests/test-ingress.yml",
"test/unit/manifests/test-service.yml"
]
// is there a more efficient way to test equality w random order?
expect(testSearch).toHaveLength(5);
expectedManifests.forEach((fileName) => {
expect(testSearch).toContain(fileName)
})
});
it("crashes when an invalid file is provided", () => {
const badPath = path.join("test", "unit", "manifests", "nonexistent.yaml")
const goodPath = path.join("test", "unit", "manifests", "manifest_test_dir")
expect(() => {getFilesFromDirectories([badPath, goodPath])}).toThrowError()
});
it("doesn't duplicate files when nested dir included", () => {
const outerPath = path.join("test", "unit", "manifests")
const fileAtOuter = path.join("test", "unit", "manifests", "test-service.yml")
const innerPath = path.join("test", "unit", "manifests", "manifest_test_dir")
expect(getFilesFromDirectories([outerPath, fileAtOuter, innerPath])).toHaveLength(5)
})
});
// files that don't exist / nested files that don't exist / something else with non-manifest
// lots of combinations of pointing to a directory and non yaml/yaml file
// similarly named files in different folders
+46
View File
@@ -61,3 +61,49 @@ function getManifestFileName(kind: string, name: string) {
const tempDirectory = getTempDirectory(); const tempDirectory = getTempDirectory();
return path.join(tempDirectory, path.basename(filePath)); return path.join(tempDirectory, path.basename(filePath));
} }
export function getFilesFromDirectories(
filePaths: string[]
): string[]{
const fullPathSet: Set<string> = new Set<string>()
filePaths.forEach((fileName => {
try {
if(fs.lstatSync(fileName).isDirectory()){
recurisveManifestGetter(fileName).forEach((file) => {fullPathSet.add(file)})
} else if(getFileExtension(fileName) === "yml" || getFileExtension(fileName) === "yaml"){
fullPathSet.add(fileName)
} else{
core.debug(`Detected non-manifest file, ${fileName}, continuing... ` )
}
} catch (ex) {
throw Error(
`Exception occurred while reading the file ${fileName}: ${ex}`
);
}
}))
return Array.from(fullPathSet)
}
function recurisveManifestGetter(dirName: string): string[]{
const toRet: string[] = []
fs.readdirSync(dirName).forEach((fileName) => {
const fnwd: string = path.join(dirName, fileName)
if(fs.lstatSync(fnwd).isDirectory()){
toRet.push(...recurisveManifestGetter(fnwd))
} else if(getFileExtension(fileName) === "yml" || getFileExtension(fileName) === "yaml"){
toRet.push(path.join(dirName, fileName))
} else{
core.debug(`Detected non-manifest file, ${fileName}, continuing... ` )
}
})
return toRet
}
function getFileExtension(fileName: string){
return fileName.slice((fileName.lastIndexOf(".") - 1 >>> 0) + 2)
}
@@ -0,0 +1,18 @@
import { prefixObjectKeys } from "../utilities/workflowAnnotationUtils";
describe("WorkflowAnnotationUtils", () => {
describe("prefixObjectKeys", () => {
it("should prefix an object with a given prefix", () => {
const obj = {
foo: "bar",
baz: "qux",
};
const prefix = "prefix.";
const expected = {
"prefix.foo": "bar",
"prefix.baz": "qux",
};
expect(prefixObjectKeys(obj, prefix)).toEqual(expected);
});
});
});
+11 -1
View File
@@ -1,5 +1,14 @@
import { DeploymentConfig } from "../types/deploymentConfig"; import { DeploymentConfig } from "../types/deploymentConfig";
const ANNOTATION_PREFIX = "actions.github.com/";
export function prefixObjectKeys(obj: any, prefix: string): any {
return Object.keys(obj).reduce((newObj, key) => {
newObj[prefix + key] = obj[key];
return newObj;
}, {});
}
export function getWorkflowAnnotations( export function getWorkflowAnnotations(
lastSuccessRunSha: string, lastSuccessRunSha: string,
workflowFilePath: string, workflowFilePath: string,
@@ -22,7 +31,8 @@ export function getWorkflowAnnotations(
helmChartPaths: deploymentConfig.helmChartFilePaths, helmChartPaths: deploymentConfig.helmChartFilePaths,
provider: "GitHub", provider: "GitHub",
}; };
return JSON.stringify(annotationObject); const prefixedAnnotationObject = prefixObjectKeys(annotationObject, ANNOTATION_PREFIX);
return JSON.stringify(prefixedAnnotationObject);
} }
export function getWorkflowAnnotationKeyLabel( export function getWorkflowAnnotationKeyLabel(
@@ -0,0 +1 @@
weaker than the average human?
+52
View File
@@ -0,0 +1,52 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: nginx-service
servicePort: 80
- path: /testpath2
backend:
serviceName: unrouted-service
servicePort: 80
+33
View File
@@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80