Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const Validations_1 = require("../Validations");
const actionparameters_1 = require("../../actionparameters");
class PublishProfileContainerWebAppValidator {
validate() {
return __awaiter(this, void 0, void 0, function* () {
const actionParams = actionparameters_1.ActionParameters.getActionParams();
Validations_1.packageNotAllowed(actionParams.packageInput);
yield Validations_1.windowsContainerAppNotAllowedForPublishProfile();
Validations_1.multiContainerNotAllowed(actionParams.multiContainerConfigFile);
Validations_1.startupCommandNotAllowed(actionParams.startupCommand);
Validations_1.validateAppDetails();
Validations_1.validateSingleContainerInputs();
});
}
}
exports.PublishProfileContainerWebAppValidator = PublishProfileContainerWebAppValidator;
31 changes: 25 additions & 6 deletions lib/ActionInputValidator/Validations.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const packageUtility_1 = require("azure-actions-utility/packageUtility");
const PublishProfile_1 = require("../Utilities/PublishProfile");
const RuntimeConstants_1 = __importDefault(require("../RuntimeConstants"));
const actionparameters_1 = require("../actionparameters");
const fs = require("fs");
// Error is app-name is not provided
Expand All @@ -31,12 +35,7 @@ exports.appNameIsRequired = appNameIsRequired;
// Error if image info is provided
function containerInputsNotAllowed(images, configFile, isPublishProfile = false) {
if (!!images || !!configFile) {
if (!!isPublishProfile) {
throw new Error("Container Deployment is not supported with publish profile credentails. Instead add an Azure login action before this action. For more details refer https://github.com/azure/login");
}
else {
throw new Error(`This is not a container web app. Please remove inputs like images and configuration-file which are only relevant for container deployment.`);
}
throw new Error(`This is not a container web app. Please remove inputs like images and configuration-file which are only relevant for container deployment.`);
}
}
exports.containerInputsNotAllowed = containerInputsNotAllowed;
Expand Down Expand Up @@ -75,6 +74,14 @@ function multiContainerNotAllowed(configFile) {
}
}
exports.multiContainerNotAllowed = multiContainerNotAllowed;
// Error if image name is not provided
function validateSingleContainerInputs() {
const actionParams = actionparameters_1.ActionParameters.getActionParams();
if (!actionParams.images) {
throw new Error("Image name not provided for container. Provide a valid image name");
}
}
exports.validateSingleContainerInputs = validateSingleContainerInputs;
// Validate container inputs
function validateContainerInputs() {
let actionParams = actionparameters_1.ActionParameters.getActionParams();
Expand Down Expand Up @@ -116,3 +123,15 @@ function validatePackageInput() {
});
}
exports.validatePackageInput = validatePackageInput;
// windows container app not allowed for publish profile auth scheme
function windowsContainerAppNotAllowedForPublishProfile() {
return __awaiter(this, void 0, void 0, function* () {
const actionParams = actionparameters_1.ActionParameters.getActionParams();
const publishProfile = PublishProfile_1.PublishProfile.getPublishProfile(actionParams.publishProfileContent);
const appOS = yield publishProfile.getAppOS();
if (appOS.includes(RuntimeConstants_1.default.Windows) || appOS.includes(RuntimeConstants_1.default.Windows.toLowerCase())) {
throw new Error("Publish profile auth scheme is not supported for Windows container Apps.");
}
});
}
exports.windowsContainerAppNotAllowedForPublishProfile = windowsContainerAppNotAllowedForPublishProfile;
23 changes: 21 additions & 2 deletions lib/ActionInputValidator/ValidatorFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,34 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const actionparameters_1 = require("../actionparameters");
const AzureResourceFilterUtility_1 = require("azure-actions-appservice-rest/Utilities/AzureResourceFilterUtility");
const BaseWebAppDeploymentProvider_1 = require("../DeploymentProvider/Providers/BaseWebAppDeploymentProvider");
const PublishProfileWebAppValidator_1 = require("./ActionValidators/PublishProfileWebAppValidator");
const PublishProfileContainerWebAppValidator_1 = require("./ActionValidators/PublishProfileContainerWebAppValidator");
const SpnLinuxContainerWebAppValidator_1 = require("./ActionValidators/SpnLinuxContainerWebAppValidator");
const SpnLinuxWebAppValidator_1 = require("./ActionValidators/SpnLinuxWebAppValidator");
const SpnWindowsContainerWebAppValidator_1 = require("./ActionValidators/SpnWindowsContainerWebAppValidator");
const SpnWindowsWebAppValidator_1 = require("./ActionValidators/SpnWindowsWebAppValidator");
const Validations_1 = require("./Validations");
const PublishProfile_1 = require("../Utilities/PublishProfile");
const RuntimeConstants_1 = __importDefault(require("../RuntimeConstants"));
class ValidatorFactory {
static getValidator(type) {
return __awaiter(this, void 0, void 0, function* () {
let actionParams = actionparameters_1.ActionParameters.getActionParams();
if (type == BaseWebAppDeploymentProvider_1.DEPLOYMENT_PROVIDER_TYPES.PUBLISHPROFILE) {
return new PublishProfileWebAppValidator_1.PublishProfileWebAppValidator();
if (type === BaseWebAppDeploymentProvider_1.DEPLOYMENT_PROVIDER_TYPES.PUBLISHPROFILE) {
yield this.setResourceDetails(actionParams);
if (!!actionParams.images) {
return new PublishProfileContainerWebAppValidator_1.PublishProfileContainerWebAppValidator();
}
else {
return new PublishProfileWebAppValidator_1.PublishProfileWebAppValidator();
}
}
else if (type == BaseWebAppDeploymentProvider_1.DEPLOYMENT_PROVIDER_TYPES.SPN) {
// app-name is required to get resource details
Expand Down Expand Up @@ -56,5 +68,12 @@ class ValidatorFactory {
params.isLinux = params.realKind.indexOf("linux") > -1;
});
}
static setResourceDetails(actionParams) {
return __awaiter(this, void 0, void 0, function* () {
const publishProfile = PublishProfile_1.PublishProfile.getPublishProfile(actionParams.publishProfileContent);
const appOS = yield publishProfile.getAppOS();
actionParams.isLinux = appOS.includes(RuntimeConstants_1.default.Unix) || appOS.includes(RuntimeConstants_1.default.Unix.toLowerCase());
});
}
}
exports.ValidatorFactory = ValidatorFactory;
9 changes: 7 additions & 2 deletions lib/DeploymentProvider/DeploymentProviderFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ const actionparameters_1 = require("../actionparameters");
const BaseWebAppDeploymentProvider_1 = require("./Providers/BaseWebAppDeploymentProvider");
const WebAppContainerDeployment_1 = require("./Providers/WebAppContainerDeployment");
const WebAppDeploymentProvider_1 = require("./Providers/WebAppDeploymentProvider");
const PublishProfileWebAppContainerDeploymentProvider_1 = require("./Providers/PublishProfileWebAppContainerDeploymentProvider");
class DeploymentProviderFactory {
static getDeploymentProvider(type) {
// For publish profile type app kind is not available so we directly return WebAppDeploymentProvider
if (type === BaseWebAppDeploymentProvider_1.DEPLOYMENT_PROVIDER_TYPES.PUBLISHPROFILE) {
return new WebAppDeploymentProvider_1.WebAppDeploymentProvider(type);
if (!!actionparameters_1.ActionParameters.getActionParams().images) {
return new PublishProfileWebAppContainerDeploymentProvider_1.PublishProfileWebAppContainerDeploymentProvider(type);
}
else {
return new WebAppDeploymentProvider_1.WebAppDeploymentProvider(type);
}
}
else if (type == BaseWebAppDeploymentProvider_1.DEPLOYMENT_PROVIDER_TYPES.SPN) {
let kind = actionparameters_1.ActionParameters.getActionParams().kind;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const PublishProfile_1 = require("../../Utilities/PublishProfile");
const actionparameters_1 = require("../../actionparameters");
const azure_app_service_1 = require("azure-actions-appservice-rest/Arm/azure-app-service");
const AzureAppServiceUtility_1 = require("azure-actions-appservice-rest/Utilities/AzureAppServiceUtility");
const azure_app_kudu_service_1 = require("azure-actions-appservice-rest/Kudu/azure-app-kudu-service");
const KuduServiceUtility_1 = require("azure-actions-appservice-rest/Utilities/KuduServiceUtility");
const AnnotationUtility_1 = require("azure-actions-appservice-rest/Utilities/AnnotationUtility");
class BaseWebAppDeploymentProvider {
Expand Down Expand Up @@ -68,9 +67,8 @@ class BaseWebAppDeploymentProvider {
}
initializeForPublishProfile() {
return __awaiter(this, void 0, void 0, function* () {
let publishProfile = PublishProfile_1.PublishProfile.getPublishProfile(this.actionParams.publishProfileContent);
let scmCreds = publishProfile.creds;
this.kuduService = new azure_app_kudu_service_1.Kudu(scmCreds.uri, scmCreds.username, scmCreds.password);
const publishProfile = PublishProfile_1.PublishProfile.getPublishProfile(this.actionParams.publishProfileContent);
this.kuduService = publishProfile.kuduService;
this.kuduServiceUtility = new KuduServiceUtility_1.KuduServiceUtility(this.kuduService);
this.applicationURL = publishProfile.appUrl;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const BaseWebAppDeploymentProvider_1 = require("./BaseWebAppDeploymentProvider");
class PublishProfileWebAppContainerDeploymentProvider extends BaseWebAppDeploymentProvider_1.BaseWebAppDeploymentProvider {
DeployWebAppStep() {
return __awaiter(this, void 0, void 0, function* () {
const appName = this.actionParams.appName;
const images = this.actionParams.images;
const isLinux = this.actionParams.isLinux;
yield this.kuduServiceUtility.deployWebAppImage(appName, images, isLinux);
});
}
}
exports.PublishProfileWebAppContainerDeploymentProvider = PublishProfileWebAppContainerDeploymentProvider;
9 changes: 9 additions & 0 deletions lib/RuntimeConstants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class RuntimeConstants {
}
exports.default = RuntimeConstants;
RuntimeConstants.system = "system";
RuntimeConstants.osName = "os_name";
RuntimeConstants.Windows = "Windows";
RuntimeConstants.Unix = "Unix";
33 changes: 33 additions & 0 deletions lib/Utilities/PublishProfile.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var core = require("@actions/core");
const actions_secret_parser_1 = require("actions-secret-parser");
const azure_app_kudu_service_1 = require("azure-actions-appservice-rest/Kudu/azure-app-kudu-service");
const RuntimeConstants_1 = __importDefault(require("../RuntimeConstants"));
class PublishProfile {
constructor(publishProfileContent) {
try {
Expand All @@ -16,6 +30,7 @@ class PublishProfile {
throw new Error("Publish profile does not contain kudu URL");
}
this._creds.uri = `https://${this._creds.uri}`;
this._kuduService = new azure_app_kudu_service_1.Kudu(this._creds.uri, this._creds.username, this._creds.password);
}
catch (error) {
core.error("Failed to fetch credentials from Publish Profile. For more details on how to set publish profile credentials refer https://aka.ms/create-secrets-for-GitHub-workflows");
Expand All @@ -34,5 +49,23 @@ class PublishProfile {
get appUrl() {
return this._appUrl;
}
get kuduService() {
return this._kuduService;
}
getAppOS() {
return __awaiter(this, void 0, void 0, function* () {
try {
if (!this._appOS) {
const appRuntimeDetails = yield this._kuduService.getAppRuntime();
this._appOS = appRuntimeDetails[RuntimeConstants_1.default.system][RuntimeConstants_1.default.osName];
core.debug(`App Runtime OS: ${this._appOS}`);
}
}
catch (error) {
throw Error("Internal Server Error. Please try again\n" + error);
}
return this._appOS;
});
}
}
exports.PublishProfile = PublishProfile;
7 changes: 3 additions & 4 deletions lib/tests/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const ValidatorFactory_1 = require("../ActionInputValidator/ValidatorFactory");
const DeploymentProviderFactory_1 = require("../DeploymentProvider/DeploymentProviderFactory");
const actionparameters_1 = require("../actionparameters");
const PublishProfileWebAppValidator_1 = require("../ActionInputValidator/ActionValidators/PublishProfileWebAppValidator");
;
const WebAppDeploymentProvider_1 = require("../DeploymentProvider/Providers/WebAppDeploymentProvider");
jest.mock('@actions/core');
jest.mock('../actionparameters');
Expand All @@ -49,9 +48,9 @@ describe('Test azure-webapps-deploy', () => {
}
return '';
});
let getValidatorFactorySpy = jest.spyOn(ValidatorFactory_1.ValidatorFactory, 'getValidator');
let getValidatorFactorySpy = jest.spyOn(ValidatorFactory_1.ValidatorFactory, 'getValidator').mockImplementation((_type) => __awaiter(void 0, void 0, void 0, function* () { return new PublishProfileWebAppValidator_1.PublishProfileWebAppValidator(); }));
let ValidatorFactoryValidateSpy = jest.spyOn(PublishProfileWebAppValidator_1.PublishProfileWebAppValidator.prototype, 'validate');
let getDeploymentProviderSpy = jest.spyOn(DeploymentProviderFactory_1.DeploymentProviderFactory, 'getDeploymentProvider');
let getDeploymentProviderSpy = jest.spyOn(DeploymentProviderFactory_1.DeploymentProviderFactory, 'getDeploymentProvider').mockImplementation(type => new WebAppDeploymentProvider_1.WebAppDeploymentProvider(type));
let deployWebAppStepSpy = jest.spyOn(WebAppDeploymentProvider_1.WebAppDeploymentProvider.prototype, 'DeployWebAppStep');
let updateDeploymentStatusSpy = jest.spyOn(WebAppDeploymentProvider_1.WebAppDeploymentProvider.prototype, 'UpdateDeploymentStatus');
try {
Expand All @@ -61,7 +60,7 @@ describe('Test azure-webapps-deploy', () => {
console.log(e);
}
expect(getAuthorizerSpy).not.toHaveBeenCalled(); // When publish profile is given as input getAuthorizer is not called
expect(getActionParamsSpy).toHaveBeenCalledTimes(2);
expect(getActionParamsSpy).toHaveBeenCalledTimes(1);
expect(getInputSpy).toHaveBeenCalledTimes(1);
expect(getValidatorFactorySpy).toHaveBeenCalledTimes(1);
expect(ValidatorFactoryValidateSpy).toHaveBeenCalledTimes(1);
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"dependencies": {
"@actions/core": "^1.2.1",
"actions-secret-parser": "^1.0.3",
"azure-actions-appservice-rest": "^1.0.9",
"azure-actions-appservice-rest": "^1.2.9",
"azure-actions-utility": "^1.0.3",
"azure-actions-webclient": "^1.0.11"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { packageNotAllowed, windowsContainerAppNotAllowedForPublishProfile, multiContainerNotAllowed, startupCommandNotAllowed, validateSingleContainerInputs, validateAppDetails } from "../Validations";
import { ActionParameters } from "../../actionparameters";
import { IValidator } from "./IValidator";

export class PublishProfileContainerWebAppValidator implements IValidator {
async validate(): Promise<void> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public async

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is just that we have been using public async in all actions. Wanted to keep it in sync. :)

const actionParams: ActionParameters = ActionParameters.getActionParams();

packageNotAllowed(actionParams.packageInput);

await windowsContainerAppNotAllowedForPublishProfile();

multiContainerNotAllowed(actionParams.multiContainerConfigFile);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra line

startupCommandNotAllowed(actionParams.startupCommand);

validateAppDetails();

validateSingleContainerInputs();
}

}
Loading