Compare commits

..

1 Commits

Author SHA1 Message Date
GitHub Action de2e93acbf build 2025-04-15 21:35:52 +00:00
9 changed files with 62 additions and 124 deletions
-6
View File
@@ -1,11 +1,5 @@
# Changelog # Changelog
## [5.0.3] - 2025-04-16
### Added
- #398 case-insensitive resource type
## [5.0.2] - 2025-04-15 ## [5.0.2] - 2025-04-15
### Added ### Added
+24 -31
View File
@@ -11914,7 +11914,7 @@ const deploymentHelper_1 = __nccwpck_require__(5959);
const trafficSplitMethod_1 = __nccwpck_require__(5187); const trafficSplitMethod_1 = __nccwpck_require__(5187);
exports.ResourceTypeManagedCluster = 'Microsoft.ContainerService/managedClusters'; exports.ResourceTypeManagedCluster = 'Microsoft.ContainerService/managedClusters';
exports.ResourceTypeFleet = 'Microsoft.ContainerService/fleets'; exports.ResourceTypeFleet = 'Microsoft.ContainerService/fleets';
function deploy(kubectl, manifestFilePaths, deploymentStrategy, resourceType) { function deploy(kubectl, manifestFilePaths, deploymentStrategy) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
// update manifests // update manifests
const inputManifestFiles = (0, manifestUpdateUtils_1.updateManifestFiles)(manifestFilePaths); const inputManifestFiles = (0, manifestUpdateUtils_1.updateManifestFiles)(manifestFilePaths);
@@ -11927,10 +11927,17 @@ function deploy(kubectl, manifestFilePaths, deploymentStrategy, resourceType) {
core.endGroup(); core.endGroup();
// check manifest stability // check manifest stability
core.startGroup('Checking manifest stability'); core.startGroup('Checking manifest stability');
const resourceTypeInput = core.getInput('resource-type') || exports.ResourceTypeManagedCluster;
const resourceTypes = (0, manifestUpdateUtils_1.getResources)(deployedManifestFiles, models.DEPLOYMENT_TYPES.concat([ const resourceTypes = (0, manifestUpdateUtils_1.getResources)(deployedManifestFiles, models.DEPLOYMENT_TYPES.concat([
KubernetesConstants.DiscoveryAndLoadBalancerResource.SERVICE KubernetesConstants.DiscoveryAndLoadBalancerResource.SERVICE
])); ]));
yield (0, deploymentHelper_1.checkManifestStability)(kubectl, resourceTypes, resourceType); if (resourceTypeInput !== exports.ResourceTypeManagedCluster &&
resourceTypeInput !== exports.ResourceTypeFleet) {
let errMsg = `Invalid resource type: ${resourceTypeInput}. Supported resource types are: ${exports.ResourceTypeManagedCluster} (default), ${exports.ResourceTypeFleet}`;
core.setFailed(errMsg);
throw new Error(errMsg);
}
yield (0, deploymentHelper_1.checkManifestStability)(kubectl, resourceTypes, resourceTypeInput);
core.endGroup(); core.endGroup();
// print ingresses // print ingresses
core.startGroup('Printing ingresses'); core.startGroup('Printing ingresses');
@@ -12015,14 +12022,15 @@ const smiBlueGreenHelper_1 = __nccwpck_require__(8886);
const deploymentStrategy_1 = __nccwpck_require__(4951); const deploymentStrategy_1 = __nccwpck_require__(4951);
const trafficSplitMethod_1 = __nccwpck_require__(5187); const trafficSplitMethod_1 = __nccwpck_require__(5187);
const routeStrategy_1 = __nccwpck_require__(2041); const routeStrategy_1 = __nccwpck_require__(2041);
function promote(kubectl, manifests, deploymentStrategy, resourceType) { const deploy_1 = __nccwpck_require__(3800);
function promote(kubectl, manifests, deploymentStrategy) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
switch (deploymentStrategy) { switch (deploymentStrategy) {
case deploymentStrategy_1.DeploymentStrategy.CANARY: case deploymentStrategy_1.DeploymentStrategy.CANARY:
yield promoteCanary(kubectl, manifests); yield promoteCanary(kubectl, manifests);
break; break;
case deploymentStrategy_1.DeploymentStrategy.BLUE_GREEN: case deploymentStrategy_1.DeploymentStrategy.BLUE_GREEN:
yield promoteBlueGreen(kubectl, manifests, resourceType); yield promoteBlueGreen(kubectl, manifests);
break; break;
default: default:
throw Error('Invalid promote deployment strategy'); throw Error('Invalid promote deployment strategy');
@@ -12074,7 +12082,7 @@ function promoteCanary(kubectl, manifests) {
core.endGroup(); core.endGroup();
}); });
} }
function promoteBlueGreen(kubectl, manifests, resourceType) { function promoteBlueGreen(kubectl, manifests) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
// update container images and pull secrets // update container images and pull secrets
const inputManifestFiles = (0, manifestUpdateUtils_1.updateManifestFiles)(manifests); const inputManifestFiles = (0, manifestUpdateUtils_1.updateManifestFiles)(manifests);
@@ -12094,10 +12102,17 @@ function promoteBlueGreen(kubectl, manifests, resourceType) {
core.endGroup(); core.endGroup();
// checking stability of newly created deployments // checking stability of newly created deployments
core.startGroup('Checking manifest stability'); core.startGroup('Checking manifest stability');
const resourceType = core.getInput('resource-type') || deploy_1.ResourceTypeManagedCluster;
const deployedManifestFiles = deployResult.manifestFiles; const deployedManifestFiles = deployResult.manifestFiles;
const resources = (0, manifestUpdateUtils_1.getResources)(deployedManifestFiles, models.DEPLOYMENT_TYPES.concat([ const resources = (0, manifestUpdateUtils_1.getResources)(deployedManifestFiles, models.DEPLOYMENT_TYPES.concat([
models.DiscoveryAndLoadBalancerResource.SERVICE models.DiscoveryAndLoadBalancerResource.SERVICE
])); ]));
if (resourceType !== deploy_1.ResourceTypeManagedCluster &&
resourceType !== deploy_1.ResourceTypeFleet) {
const errMsg = `Invalid resource type: ${resourceType}. Supported resource types are: ${deploy_1.ResourceTypeManagedCluster} (default), fleet`;
core.setFailed(errMsg);
throw new Error(errMsg);
}
yield KubernetesManifestUtility.checkManifestStability(kubectl, resources, resourceType); yield KubernetesManifestUtility.checkManifestStability(kubectl, resources, resourceType);
core.endGroup(); core.endGroup();
core.startGroup('Routing to new deployments and deleting old workloads and services'); core.startGroup('Routing to new deployments and deleting old workloads and services');
@@ -12274,10 +12289,8 @@ var __importStar = (this && this.__importStar) || (function () {
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.inputAnnotations = void 0; exports.inputAnnotations = void 0;
exports.getBufferTime = getBufferTime; exports.getBufferTime = getBufferTime;
exports.parseResourceTypeInput = parseResourceTypeInput;
const core = __importStar(__nccwpck_require__(7484)); const core = __importStar(__nccwpck_require__(7484));
const annotations_1 = __nccwpck_require__(4639); const annotations_1 = __nccwpck_require__(4639);
const deploy_1 = __nccwpck_require__(3800);
exports.inputAnnotations = (0, annotations_1.parseAnnotations)(core.getInput('annotations', { required: false })); exports.inputAnnotations = (0, annotations_1.parseAnnotations)(core.getInput('annotations', { required: false }));
function getBufferTime() { function getBufferTime() {
const inputBufferTime = parseInt(core.getInput('version-switch-buffer') || '0'); const inputBufferTime = parseInt(core.getInput('version-switch-buffer') || '0');
@@ -12285,15 +12298,6 @@ function getBufferTime() {
throw Error('Version switch buffer must be between 0 and 300 (inclusive)'); throw Error('Version switch buffer must be between 0 and 300 (inclusive)');
return inputBufferTime; return inputBufferTime;
} }
function parseResourceTypeInput(rawInput) {
switch (rawInput.toLowerCase()) {
case deploy_1.ResourceTypeFleet.toLowerCase():
return deploy_1.ResourceTypeFleet;
case deploy_1.ResourceTypeManagedCluster.toLowerCase():
return deploy_1.ResourceTypeManagedCluster;
}
throw new Error(`Invalid resource type: ${rawInput}. Supported resource types are: ${deploy_1.ResourceTypeManagedCluster} (default), ${deploy_1.ResourceTypeFleet}`);
}
/***/ }), /***/ }),
@@ -12356,7 +12360,6 @@ const action_1 = __nccwpck_require__(1695);
const deploymentStrategy_1 = __nccwpck_require__(4951); const deploymentStrategy_1 = __nccwpck_require__(4951);
const fileUtils_1 = __nccwpck_require__(8911); const fileUtils_1 = __nccwpck_require__(8911);
const privatekubectl_1 = __nccwpck_require__(7706); const privatekubectl_1 = __nccwpck_require__(7706);
const inputUtils_1 = __nccwpck_require__(1802);
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
@@ -12377,27 +12380,17 @@ function run() {
const resourceGroup = core.getInput('resource-group') || ''; const resourceGroup = core.getInput('resource-group') || '';
const resourceName = core.getInput('name') || ''; const resourceName = core.getInput('name') || '';
const skipTlsVerify = core.getBooleanInput('skip-tls-verify'); const skipTlsVerify = core.getBooleanInput('skip-tls-verify');
let resourceType;
try {
// included in the trycatch to allow raw input to go out of scope after parsing
const resourceTypeInput = core.getInput('resource-type');
resourceType = (0, inputUtils_1.parseResourceTypeInput)(resourceTypeInput);
}
catch (e) {
core.setFailed(e);
return;
}
const kubectl = isPrivateCluster const kubectl = isPrivateCluster
? new privatekubectl_1.PrivateKubectl(kubectlPath, namespace, skipTlsVerify, resourceGroup, resourceName) ? new privatekubectl_1.PrivateKubectl(kubectlPath, namespace, skipTlsVerify, resourceGroup, resourceName)
: new kubectl_1.Kubectl(kubectlPath, namespace, skipTlsVerify); : new kubectl_1.Kubectl(kubectlPath, namespace, skipTlsVerify);
// run action // run action
switch (action) { switch (action) {
case action_1.Action.DEPLOY: { case action_1.Action.DEPLOY: {
yield (0, deploy_1.deploy)(kubectl, fullManifestFilePaths, strategy, resourceType); yield (0, deploy_1.deploy)(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
case action_1.Action.PROMOTE: { case action_1.Action.PROMOTE: {
yield (0, promote_1.promote)(kubectl, fullManifestFilePaths, strategy, resourceType); yield (0, promote_1.promote)(kubectl, fullManifestFilePaths, strategy);
break; break;
} }
case action_1.Action.REJECT: { case action_1.Action.REJECT: {
@@ -15887,10 +15880,10 @@ const timeUtils_1 = __nccwpck_require__(798);
const deploy_1 = __nccwpck_require__(3800); const deploy_1 = __nccwpck_require__(3800);
const IS_SILENT = false; const IS_SILENT = false;
const POD = 'pod'; const POD = 'pod';
function checkManifestStability(kubectl, resources, resourceType) { function checkManifestStability(kubectl, resources, clusterTyper) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
// Skip if resource type is microsoft.containerservice/fleets // Skip if resource type is microsoft.containerservice/fleets
if (resourceType === deploy_1.ResourceTypeFleet) { if (clusterTyper === deploy_1.ResourceTypeFleet) {
core.info(`Skipping checkManifestStability for ${deploy_1.ResourceTypeFleet}`); core.info(`Skipping checkManifestStability for ${deploy_1.ResourceTypeFleet}`);
return; return;
} }
+17 -4
View File
@@ -13,15 +13,17 @@ import {
} from '../strategyHelpers/deploymentHelper' } from '../strategyHelpers/deploymentHelper'
import {DeploymentStrategy} from '../types/deploymentStrategy' import {DeploymentStrategy} from '../types/deploymentStrategy'
import {parseTrafficSplitMethod} from '../types/trafficSplitMethod' import {parseTrafficSplitMethod} from '../types/trafficSplitMethod'
import {ClusterType} from '../inputUtils'
export const ResourceTypeManagedCluster = export const ResourceTypeManagedCluster =
'Microsoft.ContainerService/managedClusters' 'Microsoft.ContainerService/managedClusters'
export const ResourceTypeFleet = 'Microsoft.ContainerService/fleets' export const ResourceTypeFleet = 'Microsoft.ContainerService/fleets'
export type ClusterType =
| typeof ResourceTypeManagedCluster
| typeof ResourceTypeFleet
export async function deploy( export async function deploy(
kubectl: Kubectl, kubectl: Kubectl,
manifestFilePaths: string[], manifestFilePaths: string[],
deploymentStrategy: DeploymentStrategy, deploymentStrategy: DeploymentStrategy
resourceType: ClusterType
) { ) {
// update manifests // update manifests
const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths) const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths)
@@ -43,6 +45,8 @@ export async function deploy(
// check manifest stability // check manifest stability
core.startGroup('Checking manifest stability') core.startGroup('Checking manifest stability')
const resourceTypeInput =
core.getInput('resource-type') || ResourceTypeManagedCluster
const resourceTypes: Resource[] = getResources( const resourceTypes: Resource[] = getResources(
deployedManifestFiles, deployedManifestFiles,
models.DEPLOYMENT_TYPES.concat([ models.DEPLOYMENT_TYPES.concat([
@@ -50,7 +54,16 @@ export async function deploy(
]) ])
) )
await checkManifestStability(kubectl, resourceTypes, resourceType) if (
resourceTypeInput !== ResourceTypeManagedCluster &&
resourceTypeInput !== ResourceTypeFleet
) {
let errMsg = `Invalid resource type: ${resourceTypeInput}. Supported resource types are: ${ResourceTypeManagedCluster} (default), ${ResourceTypeFleet}`
core.setFailed(errMsg)
throw new Error(errMsg)
}
await checkManifestStability(kubectl, resourceTypes, resourceTypeInput)
core.endGroup() core.endGroup()
// print ingresses // print ingresses
+14 -9
View File
@@ -38,20 +38,19 @@ import {
TrafficSplitMethod TrafficSplitMethod
} from '../types/trafficSplitMethod' } from '../types/trafficSplitMethod'
import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy' import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
import {ClusterType} from '../inputUtils' import {ResourceTypeFleet, ResourceTypeManagedCluster} from './deploy'
export async function promote( export async function promote(
kubectl: Kubectl, kubectl: Kubectl,
manifests: string[], manifests: string[],
deploymentStrategy: DeploymentStrategy, deploymentStrategy: DeploymentStrategy
resourceType: ClusterType
) { ) {
switch (deploymentStrategy) { switch (deploymentStrategy) {
case DeploymentStrategy.CANARY: case DeploymentStrategy.CANARY:
await promoteCanary(kubectl, manifests) await promoteCanary(kubectl, manifests)
break break
case DeploymentStrategy.BLUE_GREEN: case DeploymentStrategy.BLUE_GREEN:
await promoteBlueGreen(kubectl, manifests, resourceType) await promoteBlueGreen(kubectl, manifests)
break break
default: default:
throw Error('Invalid promote deployment strategy') throw Error('Invalid promote deployment strategy')
@@ -141,11 +140,7 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
core.endGroup() core.endGroup()
} }
async function promoteBlueGreen( async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) {
kubectl: Kubectl,
manifests: string[],
resourceType: ClusterType
) {
// update container images and pull secrets // update container images and pull secrets
const inputManifestFiles: string[] = updateManifestFiles(manifests) const inputManifestFiles: string[] = updateManifestFiles(manifests)
const manifestObjects: BlueGreenManifests = const manifestObjects: BlueGreenManifests =
@@ -172,6 +167,8 @@ async function promoteBlueGreen(
// checking stability of newly created deployments // checking stability of newly created deployments
core.startGroup('Checking manifest stability') core.startGroup('Checking manifest stability')
const resourceType =
core.getInput('resource-type') || ResourceTypeManagedCluster
const deployedManifestFiles = deployResult.manifestFiles const deployedManifestFiles = deployResult.manifestFiles
const resources: Resource[] = getResources( const resources: Resource[] = getResources(
deployedManifestFiles, deployedManifestFiles,
@@ -179,6 +176,14 @@ async function promoteBlueGreen(
models.DiscoveryAndLoadBalancerResource.SERVICE models.DiscoveryAndLoadBalancerResource.SERVICE
]) ])
) )
if (
resourceType !== ResourceTypeManagedCluster &&
resourceType !== ResourceTypeFleet
) {
const errMsg = `Invalid resource type: ${resourceType}. Supported resource types are: ${ResourceTypeManagedCluster} (default), fleet`
core.setFailed(errMsg)
throw new Error(errMsg)
}
await KubernetesManifestUtility.checkManifestStability( await KubernetesManifestUtility.checkManifestStability(
kubectl, kubectl,
resources, resources,
-34
View File
@@ -1,34 +0,0 @@
import {parseResourceTypeInput} from './inputUtils'
import {
ClusterType,
ResourceTypeFleet,
ResourceTypeManagedCluster
} from './actions/deploy'
describe('InputUtils', () => {
describe('parseResourceTypeInput', () => {
it('should extract fleet exact match resource type', () => {
expect(
parseResourceTypeInput('Microsoft.ContainerService/fleets')
).toEqual(ResourceTypeFleet)
})
it('should match fleet case-insensitively', () => {
expect(
parseResourceTypeInput('Microsoft.containerservice/fleets')
).toEqual(ResourceTypeFleet)
})
it('should match managed cluster case-insensitively', () => {
expect(
parseResourceTypeInput('Microsoft.containerservice/MAnaGedClusterS')
).toEqual(ResourceTypeManagedCluster)
})
it('should error on unexpected values', () => {
expect(() => {
parseResourceTypeInput('icrosoft.ContainerService/ManagedCluster')
}).toThrow()
expect(() => {
parseResourceTypeInput('wrong-value')
}).toThrow()
})
})
})
-16
View File
@@ -1,6 +1,5 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import {parseAnnotations} from './types/annotations' import {parseAnnotations} from './types/annotations'
import {ResourceTypeFleet, ResourceTypeManagedCluster} from './actions/deploy'
export const inputAnnotations = parseAnnotations( export const inputAnnotations = parseAnnotations(
core.getInput('annotations', {required: false}) core.getInput('annotations', {required: false})
@@ -15,18 +14,3 @@ export function getBufferTime(): number {
return inputBufferTime return inputBufferTime
} }
export function parseResourceTypeInput(rawInput: string): ClusterType {
switch (rawInput.toLowerCase()) {
case ResourceTypeFleet.toLowerCase():
return ResourceTypeFleet
case ResourceTypeManagedCluster.toLowerCase():
return ResourceTypeManagedCluster
}
throw new Error(
`Invalid resource type: ${rawInput}. Supported resource types are: ${ResourceTypeManagedCluster} (default), ${ResourceTypeFleet}`
)
}
export type ClusterType =
| typeof ResourceTypeManagedCluster
| typeof ResourceTypeFleet
+3 -19
View File
@@ -1,18 +1,12 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import {getKubectlPath, Kubectl} from './types/kubectl' import {getKubectlPath, Kubectl} from './types/kubectl'
import { import {deploy} from './actions/deploy'
deploy,
ResourceTypeFleet,
ResourceTypeManagedCluster
} from './actions/deploy'
import {ClusterType} from './inputUtils'
import {promote} from './actions/promote' 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 {getFilesFromDirectoriesAndURLs} from './utilities/fileUtils' import {getFilesFromDirectoriesAndURLs} from './utilities/fileUtils'
import {PrivateKubectl} from './types/privatekubectl' import {PrivateKubectl} from './types/privatekubectl'
import {parseResourceTypeInput} from './inputUtils'
export async function run() { export async function run() {
// verify kubeconfig is set // verify kubeconfig is set
@@ -42,16 +36,6 @@ export async function run() {
const resourceName = core.getInput('name') || '' const resourceName = core.getInput('name') || ''
const skipTlsVerify = core.getBooleanInput('skip-tls-verify') const skipTlsVerify = core.getBooleanInput('skip-tls-verify')
let resourceType: ClusterType
try {
// included in the trycatch to allow raw input to go out of scope after parsing
const resourceTypeInput = core.getInput('resource-type')
resourceType = parseResourceTypeInput(resourceTypeInput)
} catch (e) {
core.setFailed(e)
return
}
const kubectl = isPrivateCluster const kubectl = isPrivateCluster
? new PrivateKubectl( ? new PrivateKubectl(
kubectlPath, kubectlPath,
@@ -65,11 +49,11 @@ export async function run() {
// run action // run action
switch (action) { switch (action) {
case Action.DEPLOY: { case Action.DEPLOY: {
await deploy(kubectl, fullManifestFilePaths, strategy, resourceType) await deploy(kubectl, fullManifestFilePaths, strategy)
break break
} }
case Action.PROMOTE: { case Action.PROMOTE: {
await promote(kubectl, fullManifestFilePaths, strategy, resourceType) await promote(kubectl, fullManifestFilePaths, strategy)
break break
} }
case Action.REJECT: { case Action.REJECT: {
+1 -1
View File
@@ -35,7 +35,7 @@ import {
} from '../utilities/githubUtils' } from '../utilities/githubUtils'
import {getDeploymentConfig} from '../utilities/dockerUtils' import {getDeploymentConfig} from '../utilities/dockerUtils'
import {DeployResult} from '../types/deployResult' import {DeployResult} from '../types/deployResult'
import {ClusterType} from '../inputUtils' import {ClusterType} from '../actions/deploy'
export async function deployManifests( export async function deployManifests(
files: string[], files: string[],
+3 -4
View File
@@ -3,8 +3,7 @@ import * as KubernetesConstants from '../types/kubernetesTypes'
import {Kubectl, Resource} from '../types/kubectl' import {Kubectl, Resource} from '../types/kubectl'
import {checkForErrors} from './kubectlUtils' import {checkForErrors} from './kubectlUtils'
import {sleep} from './timeUtils' import {sleep} from './timeUtils'
import {ResourceTypeFleet} from '../actions/deploy' import {ClusterType, ResourceTypeFleet} from '../actions/deploy'
import {ClusterType} from '../inputUtils'
const IS_SILENT = false const IS_SILENT = false
const POD = 'pod' const POD = 'pod'
@@ -12,10 +11,10 @@ const POD = 'pod'
export async function checkManifestStability( export async function checkManifestStability(
kubectl: Kubectl, kubectl: Kubectl,
resources: Resource[], resources: Resource[],
resourceType: ClusterType clusterTyper: ClusterType
): Promise<void> { ): Promise<void> {
// Skip if resource type is microsoft.containerservice/fleets // Skip if resource type is microsoft.containerservice/fleets
if (resourceType === ResourceTypeFleet) { if (clusterTyper === ResourceTypeFleet) {
core.info(`Skipping checkManifestStability for ${ResourceTypeFleet}`) core.info(`Skipping checkManifestStability for ${ResourceTypeFleet}`)
return return
} }