@@ -50444,15 +50444,26 @@ function waitUntilStackOperationComplete(params, input) {
5044450444 throw new Error(`Timeout after ${maxWaitTime} seconds`);
5044550445 });
5044650446}
50447- function executeExistingChangeSet(cfn, stackName, changeSetId ) {
50448- return __awaiter(this, void 0 , void 0, function* () {
50447+ function executeExistingChangeSet(cfn_1, stackName_1, changeSetId_1 ) {
50448+ return __awaiter(this, arguments , void 0, function* (cfn, stackName, changeSetId, maxWaitTime = 21000 ) {
5044950449 core.debug(`Executing existing change set: ${changeSetId}`);
5045050450 yield cfn.send(new client_cloudformation_1.ExecuteChangeSetCommand({
5045150451 ChangeSetName: changeSetId,
5045250452 StackName: stackName
5045350453 }));
5045450454 core.debug('Waiting for CloudFormation stack operation to complete');
50455- yield waitUntilStackOperationComplete({ client: cfn, maxWaitTime: 43200, minDelay: 10 }, { StackName: stackName });
50455+ try {
50456+ yield waitUntilStackOperationComplete({ client: cfn, maxWaitTime, minDelay: 10 }, { StackName: stackName });
50457+ }
50458+ catch (error) {
50459+ if (error instanceof Error && error.message.includes('Timeout after')) {
50460+ core.warning(`Stack operation exceeded ${maxWaitTime / 60} minutes but may still be in progress. ` +
50461+ `Check AWS CloudFormation console for stack '${stackName}' status.`);
50462+ const stack = yield getStack(cfn, stackName);
50463+ return stack === null || stack === void 0 ? void 0 : stack.StackId;
50464+ }
50465+ throw error;
50466+ }
5045650467 const stack = yield getStack(cfn, stackName);
5045750468 return stack === null || stack === void 0 ? void 0 : stack.StackId;
5045850469 });
@@ -50566,8 +50577,8 @@ function cleanupChangeSet(cfn, stack, params, failOnEmptyChangeSet, noDeleteFail
5056650577 }
5056750578 });
5056850579}
50569- function updateStack(cfn, stack, params, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet ) {
50570- return __awaiter(this, void 0 , void 0, function* () {
50580+ function updateStack(cfn_1, stack_1, params_1, failOnEmptyChangeSet_1, noExecuteChangeSet_1, noDeleteFailedChangeSet_1 ) {
50581+ return __awaiter(this, arguments , void 0, function* (cfn, stack, params, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet, maxWaitTime = 21000 ) {
5057150582 var _a, _b, _c, _d;
5057250583 core.debug('Creating CloudFormation Change Set');
5057350584 const createResponse = yield cfn.send(new client_cloudformation_1.CreateChangeSetCommand(params));
@@ -50600,13 +50611,19 @@ function updateStack(cfn, stack, params, failOnEmptyChangeSet, noExecuteChangeSe
5060050611 try {
5060150612 yield waitUntilStackOperationComplete({
5060250613 client: cfn,
50603- maxWaitTime: 43200 ,
50614+ maxWaitTime,
5060450615 minDelay: 10
5060550616 }, {
5060650617 StackName: params.StackName
5060750618 });
5060850619 }
5060950620 catch (error) {
50621+ // Handle timeout gracefully
50622+ if (error instanceof Error && error.message.includes('Timeout after')) {
50623+ core.warning(`Stack operation exceeded ${maxWaitTime / 60} minutes but may still be in progress. ` +
50624+ `Check AWS CloudFormation console for stack '${params.StackName}' status.`);
50625+ return { stackId: stack.StackId };
50626+ }
5061050627 // Get execution failure details using OperationId
5061150628 const stackResponse = yield cfn.send(new client_cloudformation_1.DescribeStacksCommand({ StackName: params.StackName }));
5061250629 const executionOp = (_c = (_b = (_a = stackResponse.Stacks) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.LastOperations) === null || _c === void 0 ? void 0 : _c.find(op => op.OperationType === 'UPDATE_STACK' ||
@@ -50684,17 +50701,17 @@ function buildUpdateChangeSetParams(params, changeSetName) {
5068450701 DeploymentMode: params.DeploymentMode // Only valid for UPDATE change sets
5068550702 };
5068650703}
50687- function deployStack(cfn, params, changeSetName, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet ) {
50688- return __awaiter(this, void 0 , void 0, function* () {
50704+ function deployStack(cfn_1, params_1, changeSetName_1, failOnEmptyChangeSet_1, noExecuteChangeSet_1, noDeleteFailedChangeSet_1 ) {
50705+ return __awaiter(this, arguments , void 0, function* (cfn, params, changeSetName, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet, maxWaitTime = 21000 ) {
5068950706 const stack = yield getStack(cfn, params.StackName);
5069050707 if (!stack) {
5069150708 core.debug(`Creating CloudFormation Stack via Change Set`);
5069250709 const createParams = buildCreateChangeSetParams(params, changeSetName);
50693- return yield updateStack(cfn, { StackId: undefined }, createParams, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet);
50710+ return yield updateStack(cfn, { StackId: undefined }, createParams, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet, maxWaitTime );
5069450711 }
5069550712 core.debug(`Updating CloudFormation Stack via Change Set`);
5069650713 const updateParams = buildUpdateChangeSetParams(params, changeSetName);
50697- return yield updateStack(cfn, stack, updateParams, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet);
50714+ return yield updateStack(cfn, stack, updateParams, failOnEmptyChangeSet, noExecuteChangeSet, noDeleteFailedChangeSet, maxWaitTime );
5069850715 });
5069950716}
5070050717function getStackOutputs(cfn, stackId) {
@@ -50834,7 +50851,13 @@ function run() {
5083450851 const cfn = new client_cloudformation_1.CloudFormationClient(Object.assign({}, clientConfiguration));
5083550852 // Execute existing change set mode
5083650853 if (inputs.mode === 'execute-only') {
50837- const stackId = yield (0, deploy_1.executeExistingChangeSet)(cfn, inputs.name, inputs['execute-change-set-id']);
50854+ // Calculate maxWaitTime for execute-only mode
50855+ const defaultMaxWaitTime = 21000; // 5 hours 50 minutes in seconds
50856+ const timeoutMinutes = inputs['timeout-in-minutes'];
50857+ const maxWaitTime = typeof timeoutMinutes === 'number'
50858+ ? timeoutMinutes * 60
50859+ : defaultMaxWaitTime;
50860+ const stackId = yield (0, deploy_1.executeExistingChangeSet)(cfn, inputs.name, inputs['execute-change-set-id'], maxWaitTime);
5083850861 core.setOutput('stack-id', stackId || 'UNKNOWN');
5083950862 if (stackId) {
5084050863 const outputs = yield (0, deploy_1.getStackOutputs)(cfn, stackId);
@@ -50874,7 +50897,13 @@ function run() {
5087450897 DeploymentMode: inputs['deployment-mode'],
5087550898 Parameters: inputs['parameter-overrides']
5087650899 };
50877- const result = yield (0, deploy_1.deployStack)(cfn, params, inputs['change-set-name'] || `${params.StackName}-CS`, inputs['fail-on-empty-changeset'], inputs['no-execute-changeset'] || inputs.mode === 'create-only', inputs['no-delete-failed-changeset']);
50900+ // Calculate maxWaitTime: use timeout-in-minutes if provided, otherwise default to 5h50m (safe for GitHub Actions 6h limit)
50901+ const defaultMaxWaitTime = 21000; // 5 hours 50 minutes in seconds
50902+ const timeoutMinutes = inputs['timeout-in-minutes'];
50903+ const maxWaitTime = typeof timeoutMinutes === 'number'
50904+ ? timeoutMinutes * 60
50905+ : defaultMaxWaitTime;
50906+ const result = yield (0, deploy_1.deployStack)(cfn, params, inputs['change-set-name'] || `${params.StackName}-CS`, inputs['fail-on-empty-changeset'], inputs['no-execute-changeset'] || inputs.mode === 'create-only', inputs['no-delete-failed-changeset'], maxWaitTime);
5087850907 core.setOutput('stack-id', result.stackId || 'UNKNOWN');
5087950908 // Set change set outputs when not executing
5088050909 if (result.changeSetInfo) {
0 commit comments