mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-06-21 10:39:26 +08:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b0b5178d5 | |||
| d43ff40a3e | |||
| 507f2d4fc7 | |||
| 06a06b13b9 | |||
| fa093f2922 | |||
| aabcfcba3e | |||
| fd893fd074 | |||
| 659e414483 | |||
| 1e490c6238 | |||
| 75cb5d47f7 | |||
| bcdb90f36f |
@@ -21,11 +21,15 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Building latest changes
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
rm -rf node_modules/
|
||||
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
|
||||
run: echo "::set-output name=name::$(echo `date +%Y%m%d%H%M%S`)"
|
||||
|
||||
@@ -42,7 +42,7 @@ Following are the key capabilities of this action:
|
||||
</tr>
|
||||
<tr>
|
||||
<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>
|
||||
<td>namespace </br></br>(Optional)
|
||||
@@ -57,6 +57,10 @@ Following are the key capabilities of this action:
|
||||
<tr>
|
||||
<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>
|
||||
</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>
|
||||
<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>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>
|
||||
<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>
|
||||
|
||||
## Usage Examples
|
||||
@@ -97,23 +105,21 @@ Following are the key capabilities of this action:
|
||||
### Basic deployment (without any deployment strategy)
|
||||
|
||||
```yaml
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
namespace: "myapp"
|
||||
manifests: |
|
||||
deployment.yaml
|
||||
service.yaml
|
||||
dir/manifestsDirectory
|
||||
images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
|
||||
imagepullsecrets: |
|
||||
image-pull-secret1
|
||||
image-pull-secret2
|
||||
kubectl-version: "latest"
|
||||
```
|
||||
|
||||
### Canary deployment without service mesh
|
||||
|
||||
```yaml
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
namespace: "myapp"
|
||||
images: "contoso.azurecr.io/myapp:${{ event.run_id }}"
|
||||
@@ -123,6 +129,7 @@ Following are the key capabilities of this action:
|
||||
manifests: |
|
||||
deployment.yaml
|
||||
service.yaml
|
||||
dir/manifestsDirectory
|
||||
strategy: canary
|
||||
action: deploy
|
||||
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:
|
||||
|
||||
```yaml
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
namespace: "myapp"
|
||||
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: |
|
||||
deployment.yaml
|
||||
service.yaml
|
||||
dir/manifestsDirectory
|
||||
strategy: canary
|
||||
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
|
||||
|
||||
```yaml
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
namespace: "myapp"
|
||||
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: |
|
||||
deployment.yaml
|
||||
service.yaml
|
||||
dir/manifestsDirectory
|
||||
strategy: canary
|
||||
action: deploy
|
||||
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:
|
||||
|
||||
```yaml
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
namespace: "myapp"
|
||||
images: "contoso.azurecr.io/myapp:${{ event.run_id }} "
|
||||
@@ -178,15 +187,16 @@ To promote/reject the canary created by the above snippet, the following YAML sn
|
||||
manifests: |
|
||||
deployment.yaml
|
||||
service.yaml
|
||||
dir/manifestsDirectory
|
||||
strategy: canary
|
||||
traffic-split-method: smi
|
||||
action: reject # substitute reject if you want to reject
|
||||
action: reject # substitute promote if you want to promote
|
||||
```
|
||||
|
||||
### Blue-Green deployment with different route methods
|
||||
|
||||
```yaml
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
namespace: "myapp"
|
||||
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:
|
||||
|
||||
```yaml
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
namespace: "myapp"
|
||||
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: |
|
||||
deployment.yaml
|
||||
service.yaml
|
||||
ingress-yml
|
||||
ingress.yml
|
||||
strategy: blue-green
|
||||
route-method: ingress # should be the same as the value when action was deploy
|
||||
action: promote # substitute reject if you want to reject
|
||||
@@ -263,7 +273,7 @@ jobs:
|
||||
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
secret-name: demo-k8s-secret
|
||||
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
action: deploy
|
||||
manifests: |
|
||||
@@ -309,7 +319,7 @@ jobs:
|
||||
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
secret-name: demo-k8s-secret
|
||||
|
||||
- uses: Azure/k8s-deploy@v1.4
|
||||
- uses: Azure/k8s-deploy@v3.1
|
||||
with:
|
||||
action: deploy
|
||||
manifests: |
|
||||
|
||||
@@ -15,6 +15,10 @@ inputs:
|
||||
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"
|
||||
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:
|
||||
description: "Deployment strategy to be used. Allowed values are none, canary and blue-green"
|
||||
required: false
|
||||
@@ -51,6 +55,10 @@ inputs:
|
||||
description: "Github token"
|
||||
default: ${{ github.token }}
|
||||
required: true
|
||||
annotate-namespace:
|
||||
description: "Annotate the target namespace"
|
||||
required: false
|
||||
default: true
|
||||
|
||||
branding:
|
||||
color: "green"
|
||||
|
||||
Generated
+18
-18
@@ -1243,9 +1243,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -4083,9 +4083,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mixin-deep": {
|
||||
@@ -5573,9 +5573,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tmpl": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
|
||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
@@ -7115,9 +7115,9 @@
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
@@ -9320,9 +9320,9 @@
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"mixin-deep": {
|
||||
@@ -10513,9 +10513,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"tmpl": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
|
||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
|
||||
"dev": true
|
||||
},
|
||||
"to-fast-properties": {
|
||||
|
||||
+6
-4
@@ -5,6 +5,7 @@ import { promote } from "./actions/promote";
|
||||
import { reject } from "./actions/reject";
|
||||
import { Action, parseAction } from "./types/action";
|
||||
import { parseDeploymentStrategy } from "./types/deploymentStrategy";
|
||||
import { getFilesFromDirectories } from "./utilities/fileUtils";
|
||||
|
||||
export async function run() {
|
||||
// verify kubeconfig is set
|
||||
@@ -23,7 +24,8 @@ export async function run() {
|
||||
.split(/[\n,;]+/) // split into each individual manifest
|
||||
.map((manifest) => manifest.trim()) // remove surrounding whitespace
|
||||
.filter((manifest) => manifest.length > 0); // remove any blanks
|
||||
|
||||
|
||||
const fullManifestFilePaths = getFilesFromDirectories(manifestFilePaths)
|
||||
// create kubectl
|
||||
const kubectlPath = await getKubectlPath();
|
||||
const namespace = core.getInput("namespace") || "default";
|
||||
@@ -32,15 +34,15 @@ export async function run() {
|
||||
// run action
|
||||
switch (action) {
|
||||
case Action.DEPLOY: {
|
||||
await deploy(kubectl, manifestFilePaths, strategy);
|
||||
await deploy(kubectl, fullManifestFilePaths, strategy);
|
||||
break;
|
||||
}
|
||||
case Action.PROMOTE: {
|
||||
await promote(kubectl, manifestFilePaths, strategy);
|
||||
await promote(kubectl, fullManifestFilePaths, strategy);
|
||||
break;
|
||||
}
|
||||
case Action.REJECT: {
|
||||
await reject(kubectl, manifestFilePaths, strategy);
|
||||
await reject(kubectl, fullManifestFilePaths, strategy);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -173,9 +173,13 @@ async function annotateResources(
|
||||
workflowFilePath,
|
||||
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));
|
||||
|
||||
for (const resource of resourceTypes) {
|
||||
|
||||
@@ -26,14 +26,17 @@ export async function getDeploymentConfig(): Promise<DeploymentConfig> {
|
||||
const imageNames = core.getInput("images").split("\n") || [];
|
||||
const imageDockerfilePathMap: { [id: string]: string } = {};
|
||||
|
||||
//Fetching from image label if available
|
||||
for (const image of imageNames) {
|
||||
try {
|
||||
imageDockerfilePathMap[image] = await getDockerfilePath(image);
|
||||
} catch (ex) {
|
||||
core.warning(
|
||||
`Failed to get dockerfile path for image ${image.toString()}: ${ex} `
|
||||
);
|
||||
const pullImages = !(core.getInput("pull-images").toLowerCase() === "false");
|
||||
if (pullImages) {
|
||||
//Fetching from image label if available
|
||||
for (const image of imageNames) {
|
||||
try {
|
||||
imageDockerfilePathMap[image] = await getDockerfilePath(image);
|
||||
} catch (ex) {
|
||||
core.warning(
|
||||
`Failed to get dockerfile path for image ${image.toString()}: ${ex} `
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -61,3 +61,49 @@ function getManifestFileName(kind: string, name: string) {
|
||||
const tempDirectory = getTempDirectory();
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,14 @@
|
||||
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(
|
||||
lastSuccessRunSha: string,
|
||||
workflowFilePath: string,
|
||||
@@ -22,7 +31,8 @@ export function getWorkflowAnnotations(
|
||||
helmChartPaths: deploymentConfig.helmChartFilePaths,
|
||||
provider: "GitHub",
|
||||
};
|
||||
return JSON.stringify(annotationObject);
|
||||
const prefixedAnnotationObject = prefixObjectKeys(annotationObject, ANNOTATION_PREFIX);
|
||||
return JSON.stringify(prefixedAnnotationObject);
|
||||
}
|
||||
|
||||
export function getWorkflowAnnotationKeyLabel(
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
weaker than the average human?
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user