Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions __tests__/DeploymentProvider/BaseWebAppDeploymentProvider.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { DEPLOYMENT_PROVIDER_TYPES } from '../../src/DeploymentProvider/Providers/BaseWebAppDeploymentProvider';

// Mock dependencies
jest.mock('@actions/core');
jest.mock('../../src/actionparameters');
jest.mock('azure-actions-appservice-rest/Arm/azure-app-service');
jest.mock('azure-actions-appservice-rest/Utilities/AzureAppServiceUtility');
jest.mock('azure-actions-appservice-rest/Kudu/azure-app-kudu-service');
jest.mock('azure-actions-appservice-rest/Utilities/KuduServiceUtility');

import * as core from '@actions/core';
import { ActionParameters } from '../../src/actionparameters';
import { AzureAppServiceUtility } from 'azure-actions-appservice-rest/Utilities/AzureAppServiceUtility';

describe('Test BaseWebAppDeploymentProvider', () => {

beforeEach(() => {
jest.clearAllMocks();

// Mock ActionParameters
(ActionParameters.getActionParams as jest.Mock) = jest.fn().mockReturnValue({
endpoint: {},
resourceGroupName: 'test-rg',
appName: 'test-app',
slotName: 'production'
});
});

describe('getWarmupInstanceId', () => {

it('should return first instance when sorted alphabetically', async () => {
// Arrange
const mockInstances = {
value: [
{ name: 'instance-c' },
{ name: 'instance-a' },
{ name: 'instance-b' }
]
};

const mockGetAppserviceInstances = jest.fn().mockResolvedValue(mockInstances);
const mockGetKuduService = jest.fn().mockResolvedValue({});
const mockGetApplicationURL = jest.fn().mockResolvedValue('https://test-app.azurewebsites.net');

(AzureAppServiceUtility as jest.Mock).mockImplementation(() => ({
getAppserviceInstances: mockGetAppserviceInstances,
getKuduService: mockGetKuduService,
getApplicationURL: mockGetApplicationURL
}));

// Act - We need to create a concrete implementation to test
const { WebAppDeploymentProvider } = await import('../../src/DeploymentProvider/Providers/WebAppDeploymentProvider');
const provider = new WebAppDeploymentProvider(DEPLOYMENT_PROVIDER_TYPES.SPN);
await provider.PreDeploymentStep();

// Assert
expect(mockGetAppserviceInstances).toHaveBeenCalled();
// instance-a should be selected (first alphabetically)
expect(mockGetKuduService).toHaveBeenCalledWith('instance-a');
});

it('should return undefined when no instances are available', async () => {
// Arrange
const mockGetAppserviceInstances = jest.fn().mockResolvedValue({ value: [] });
const mockGetKuduService = jest.fn().mockResolvedValue({});
const mockGetApplicationURL = jest.fn().mockResolvedValue('https://test-app.azurewebsites.net');

(AzureAppServiceUtility as jest.Mock).mockImplementation(() => ({
getAppserviceInstances: mockGetAppserviceInstances,
getKuduService: mockGetKuduService,
getApplicationURL: mockGetApplicationURL
}));

// Act
const { WebAppDeploymentProvider } = await import('../../src/DeploymentProvider/Providers/WebAppDeploymentProvider');
const provider = new WebAppDeploymentProvider(DEPLOYMENT_PROVIDER_TYPES.SPN);
await provider.PreDeploymentStep();

// Assert
expect(mockGetKuduService).toHaveBeenCalledWith(undefined);
});

it('should handle errors gracefully and return undefined', async () => {
// Arrange
const mockGetAppserviceInstances = jest.fn().mockRejectedValue(new Error('API Error'));
const mockGetKuduService = jest.fn().mockResolvedValue({});
const mockGetApplicationURL = jest.fn().mockResolvedValue('https://test-app.azurewebsites.net');

(AzureAppServiceUtility as jest.Mock).mockImplementation(() => ({
getAppserviceInstances: mockGetAppserviceInstances,
getKuduService: mockGetKuduService,
getApplicationURL: mockGetApplicationURL
}));

// Act
const { WebAppDeploymentProvider } = await import('../../src/DeploymentProvider/Providers/WebAppDeploymentProvider');
const provider = new WebAppDeploymentProvider(DEPLOYMENT_PROVIDER_TYPES.SPN);
await provider.PreDeploymentStep();

// Assert
expect(core.debug).toHaveBeenCalledWith(expect.stringContaining('Failed to get app service instances'));
expect(mockGetKuduService).toHaveBeenCalledWith(undefined);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ class BaseWebAppDeploymentProvider {
return __awaiter(this, void 0, void 0, function* () {
this.appService = new azure_app_service_1.AzureAppService(this.actionParams.endpoint, this.actionParams.resourceGroupName, this.actionParams.appName, this.actionParams.slotName);
this.appServiceUtility = new AzureAppServiceUtility_1.AzureAppServiceUtility(this.appService);
this.kuduService = yield this.appServiceUtility.getKuduService();
const warmupInstanceId = yield this.getWarmupInstanceId();
core.debug(`Warmup Instance Id: ${warmupInstanceId}`);
this.kuduService = yield this.appServiceUtility.getKuduService(warmupInstanceId);
this.kuduServiceUtility = new KuduServiceUtility_1.KuduServiceUtility(this.kuduService);
this.applicationURL = yield this.appServiceUtility.getApplicationURL();
});
Expand All @@ -100,6 +102,24 @@ class BaseWebAppDeploymentProvider {
this.applicationURL = publishProfile.appUrl;
});
}
// Get the warmup instance id.
getWarmupInstanceId() {
return __awaiter(this, void 0, void 0, function* () {
var _a;
try {
const instances = yield this.appServiceUtility.getAppserviceInstances();
if (((_a = instances === null || instances === void 0 ? void 0 : instances.value) === null || _a === void 0 ? void 0 : _a.length) > 0) {
// Sort by name and pick the first one.
const sortedInstances = instances.value.sort((a, b) => a.name.localeCompare(b.name));
return sortedInstances[0].name;
}
}
catch (error) {
core.debug(`Failed to get app service instances - ${error}`);
}
return undefined;
});
}
}
exports.BaseWebAppDeploymentProvider = BaseWebAppDeploymentProvider;
var DEPLOYMENT_PROVIDER_TYPES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class WebAppDeploymentProvider extends BaseWebAppDeploymentProvider_1.BaseWebApp
let webPackage = appPackage.getPath();
const validTypes = ["war", "jar", "ear", "zip", "static"];
// kudu warm up
yield this.kuduServiceUtility.warmpUp();
yield this.kuduServiceUtility.warmUp();
// If provided, type paramater takes precidence over file package type
if (this.actionParams.type != null && validTypes.includes(this.actionParams.type.toLowerCase())) {
core.debug("Initiated deployment via kudu service for webapp" + this.actionParams.type + "package : " + webPackage);
Expand Down
Loading
Loading