diff --git a/.gitattributes b/.gitattributes index 989136c25..616f04d9a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -42,6 +42,7 @@ /src/backend/inventory/canary.ts linguist-generated /src/backend/inventory/package-versions-table-widget-function.ts linguist-generated /src/backend/orchestration/needs-catalog-update.ts linguist-generated +/src/backend/orchestration/read-uninstallable-report.ts linguist-generated /src/backend/orchestration/redrive-state-machine.ts linguist-generated /src/backend/package-stats/package-stats-aggregator.ts linguist-generated /src/backend/package-stats/package-stats-chunker.ts linguist-generated diff --git a/.gitignore b/.gitignore index 6a4cbd31e..4b29e8184 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,7 @@ lib/__tests__/devapp/cdk.out !/src/backend/package-stats/package-stats-chunker.ts !/src/backend/package-stats/package-stats-aggregator.ts !/src/backend/orchestration/redrive-state-machine.ts +!/src/backend/orchestration/read-uninstallable-report.ts !/src/backend/orchestration/needs-catalog-update.ts !/src/backend/inventory/package-versions-table-widget-function.ts !/src/backend/inventory/canary.ts diff --git a/.prettierignore b/.prettierignore index 3333bff2e..fe590039e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -15,6 +15,7 @@ src/backend/package-stats/package-stats-processor.ts src/backend/package-stats/package-stats-chunker.ts src/backend/package-stats/package-stats-aggregator.ts src/backend/orchestration/redrive-state-machine.ts +src/backend/orchestration/read-uninstallable-report.ts src/backend/orchestration/needs-catalog-update.ts src/backend/inventory/package-versions-table-widget-function.ts src/backend/inventory/canary.ts diff --git a/.projen/files.json b/.projen/files.json index 2183f5664..ba9973500 100644 --- a/.projen/files.json +++ b/.projen/files.json @@ -36,6 +36,7 @@ "src/backend/inventory/canary.ts", "src/backend/inventory/package-versions-table-widget-function.ts", "src/backend/orchestration/needs-catalog-update.ts", + "src/backend/orchestration/read-uninstallable-report.ts", "src/backend/orchestration/redrive-state-machine.ts", "src/backend/package-stats/package-stats-aggregator.ts", "src/backend/package-stats/package-stats-chunker.ts", diff --git a/.projen/tasks.json b/.projen/tasks.json index c41f6d7fd..9a40ffd48 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -95,6 +95,9 @@ { "spawn": "bundle:redrive-state-machine" }, + { + "spawn": "bundle:read-uninstallable-report" + }, { "spawn": "bundle:needs-catalog-update" }, @@ -333,7 +336,7 @@ "description": "Continuously bundle all AWS Lambda functions", "steps": [ { - "exec": "esbuild --bundle src/package-sources/npmjs/stage-and-notify.lambda.ts src/package-sources/npmjs/re-stage-package-version.lambda.ts src/package-sources/npmjs/npm-js-follower.lambda.ts src/package-sources/npmjs/canary/npmjs-package-canary.lambda.ts src/package-sources/codeartifact/code-artifact-forwarder.lambda.ts src/overview-dashboard/sqs-dlq-stats-widget-function.lambda.ts src/monitoring/http-get-function.lambda.ts src/monitored-certificate/certificate-monitor.lambda.ts src/backend/version-tracker/version-tracker.lambda.ts src/backend/release-notes/release-notes-trigger.lambda.ts src/backend/release-notes/get-messages-from-worker-queue.lambda.ts src/backend/release-notes/generate-release-notes.lambda.ts src/backend/package-stats/package-stats-processor.lambda.ts src/backend/package-stats/package-stats-chunker.lambda.ts src/backend/package-stats/package-stats-aggregator.lambda.ts src/backend/orchestration/redrive-state-machine.lambda.ts src/backend/orchestration/needs-catalog-update.lambda.ts src/backend/inventory/package-versions-table-widget-function.lambda.ts src/backend/inventory/canary.lambda.ts src/backend/ingestion/re-ingest.lambda.ts src/backend/ingestion/ingestion.lambda.ts src/backend/feed-builder/update-feed.lambda.ts src/backend/ecs-task-monitor/monitor.lambda.ts src/backend/deny-list/prune-queue-handler.lambda.ts src/backend/deny-list/prune-handler.lambda.ts src/backend/catalog-builder/catalog-builder.lambda.ts src/__tests__/backend/deny-list/mocks/prune-test.lambda.ts src/__tests__/backend/deny-list/mocks/client-test.lambda.ts src/__tests__/backend/deny-list/mocks/catalog-builder-mock.lambda.ts --target=\"node22 --platform=\"node\" --outbase=\"src\" --outdir=\"lib\" --entry-names=\"[dir]/[name].bundle/index\" --external:aws-sdk --sourcemap --watch --tsconfig=tsconfig.dev.json" + "exec": "esbuild --bundle src/package-sources/npmjs/stage-and-notify.lambda.ts src/package-sources/npmjs/re-stage-package-version.lambda.ts src/package-sources/npmjs/npm-js-follower.lambda.ts src/package-sources/npmjs/canary/npmjs-package-canary.lambda.ts src/package-sources/codeartifact/code-artifact-forwarder.lambda.ts src/overview-dashboard/sqs-dlq-stats-widget-function.lambda.ts src/monitoring/http-get-function.lambda.ts src/monitored-certificate/certificate-monitor.lambda.ts src/backend/version-tracker/version-tracker.lambda.ts src/backend/release-notes/release-notes-trigger.lambda.ts src/backend/release-notes/get-messages-from-worker-queue.lambda.ts src/backend/release-notes/generate-release-notes.lambda.ts src/backend/package-stats/package-stats-processor.lambda.ts src/backend/package-stats/package-stats-chunker.lambda.ts src/backend/package-stats/package-stats-aggregator.lambda.ts src/backend/orchestration/redrive-state-machine.lambda.ts src/backend/orchestration/read-uninstallable-report.lambda.ts src/backend/orchestration/needs-catalog-update.lambda.ts src/backend/inventory/package-versions-table-widget-function.lambda.ts src/backend/inventory/canary.lambda.ts src/backend/ingestion/re-ingest.lambda.ts src/backend/ingestion/ingestion.lambda.ts src/backend/feed-builder/update-feed.lambda.ts src/backend/ecs-task-monitor/monitor.lambda.ts src/backend/deny-list/prune-queue-handler.lambda.ts src/backend/deny-list/prune-handler.lambda.ts src/backend/catalog-builder/catalog-builder.lambda.ts src/__tests__/backend/deny-list/mocks/prune-test.lambda.ts src/__tests__/backend/deny-list/mocks/client-test.lambda.ts src/__tests__/backend/deny-list/mocks/catalog-builder-mock.lambda.ts --target=\"node22 --platform=\"node\" --outbase=\"src\" --outdir=\"lib\" --entry-names=\"[dir]/[name].bundle/index\" --external:aws-sdk --sourcemap --watch --tsconfig=tsconfig.dev.json" } ] }, @@ -571,6 +574,24 @@ } ] }, + "bundle:read-uninstallable-report": { + "name": "bundle:read-uninstallable-report", + "description": "Create an AWS Lambda bundle from src/backend/orchestration/read-uninstallable-report.lambda.ts", + "steps": [ + { + "exec": "esbuild --bundle src/backend/orchestration/read-uninstallable-report.lambda.ts --target=\"node22\" --platform=\"node\" --outfile=\"lib/backend/orchestration/read-uninstallable-report.lambda.bundle/index.js\" --external:aws-sdk --sourcemap --tsconfig=tsconfig.dev.json" + } + ] + }, + "bundle:read-uninstallable-report:watch": { + "name": "bundle:read-uninstallable-report:watch", + "description": "Continuously update an AWS Lambda bundle from src/backend/orchestration/read-uninstallable-report.lambda.ts", + "steps": [ + { + "exec": "esbuild --bundle src/backend/orchestration/read-uninstallable-report.lambda.ts --target=\"node22\" --platform=\"node\" --outfile=\"lib/backend/orchestration/read-uninstallable-report.lambda.bundle/index.js\" --external:aws-sdk --sourcemap --tsconfig=tsconfig.dev.json --watch" + } + ] + }, "bundle:redrive-state-machine": { "name": "bundle:redrive-state-machine", "description": "Create an AWS Lambda bundle from src/backend/orchestration/redrive-state-machine.lambda.ts", @@ -811,6 +832,9 @@ { "spawn": "bundle:redrive-state-machine" }, + { + "spawn": "bundle:read-uninstallable-report" + }, { "spawn": "bundle:needs-catalog-update" }, diff --git a/docs/operator-runbook.md b/docs/operator-runbook.md index 29620554d..2ba54daa5 100644 --- a/docs/operator-runbook.md +++ b/docs/operator-runbook.md @@ -681,6 +681,57 @@ Two workflows are available for reprocessing of individual items: } ``` +## :package: Missing Package Documentation + +### Description + +When documentation for a package is not available, it could be due to several reasons: + +1. **Uninstallable Package**: The package cannot be installed during the documentation generation process +2. **Corrupt Assembly**: The package's assembly.json file is corrupted or invalid +3. **Transliteration Error**: The documentation generation process failed for a specific language +4. **Missing Dependencies**: Required dependencies are not available + +### Investigation + +1. **Check the Uninstallable Packages Report**: In the backend dashboard, review the "Package Versions Report | Uninstallable" section to see if the package is listed as uninstallable. + +2. **Review Package Directory**: Check the package's S3 directory (`data//v/`) for error marker files: + - `uninstallable` - Package cannot be installed + - `*.corruptassembly` - Assembly file is corrupted + - `*.transliteration-failed` - Transliteration failed for a language + +3. **Check Orchestration Logs**: Review the orchestration state machine execution logs for the specific package to identify the failure point. + +4. **Examine ECS Task Logs**: If the failure occurred during documentation generation, check the ECS task logs in CloudWatch for detailed error messages. + +### Resolution + +1. **For Uninstallable Packages**: Use the "Retry Uninstallable Packages" button in the backend dashboard to automatically retry all uninstallable packages. This will: + - Read the current uninstallable packages report + - Trigger reprocessing for each uninstallable package + - Note: The inventory report will be updated automatically by the scheduled inventory canary, but it processes packages incrementally, so it may take a few hours for all changes to be fully reflected in the dashboard + - Warning: This may trigger `Orchestration/Resource/ExecutionsFailed` and `Orchestration/DLQ/NotEmpty` alarms since some packages may still fail on retry and be sent to the dead letter queue + +2. **For Individual Packages**: Use the "ReprocessDocumentationPerPackage" state machine to retry a specific package: + ```json + { + "Prefix": "data//v" + } + ``` + +3. **For Systematic Issues**: If many packages are failing, investigate the root cause: + - Check if there are issues with the documentation generation tooling + - Verify that all required dependencies and services are available + - Review recent changes to the transliterator or documentation generator + +### Prevention + +- Monitor the uninstallable packages count metric regularly +- Set up alerts for increases in missing documentation +- Regularly review and update the documentation generation tooling +- Ensure proper testing of changes to the transliterator pipeline + -------------------------------------------------------------------------------- ### `ConstructHub/Sources/NpmJs/Canary/SLA-Breached` diff --git a/package.json b/package.json index 839f61229..8e001f9a8 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,8 @@ "bundle:re-ingest:watch": "npx projen bundle:re-ingest:watch", "bundle:re-stage-package-version": "npx projen bundle:re-stage-package-version", "bundle:re-stage-package-version:watch": "npx projen bundle:re-stage-package-version:watch", + "bundle:read-uninstallable-report": "npx projen bundle:read-uninstallable-report", + "bundle:read-uninstallable-report:watch": "npx projen bundle:read-uninstallable-report:watch", "bundle:redrive-state-machine": "npx projen bundle:redrive-state-machine", "bundle:redrive-state-machine:watch": "npx projen bundle:redrive-state-machine:watch", "bundle:release-notes-trigger": "npx projen bundle:release-notes-trigger", diff --git a/src/__tests__/__snapshots__/construct-hub.test.ts.snap b/src/__tests__/__snapshots__/construct-hub.test.ts.snap index 09e12088e..fb379e774 100644 --- a/src/__tests__/__snapshots__/construct-hub.test.ts.snap +++ b/src/__tests__/__snapshots__/construct-hub.test.ts.snap @@ -926,6 +926,10 @@ def sort_filter_rules(json_obj): { "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254", }, + ")\\n[button:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, ")"}},{"type":"metric","width":12,"height":6,"x":0,"y":99,"properties":{"view":"timeSeries","title":"State Machine Executions","region":"", { "Ref": "AWS::Region", @@ -1118,7 +1122,11 @@ def sort_filter_rules(json_obj): "Arn", ], }, - "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", + "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n\\n[button:primary:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, + ")\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", { "Fn::GetAtt": [ "PackageVersionsTableWidgetHandler5fa848259c1d5e388c0df69f05c016dfBE2C27C2", @@ -6826,6 +6834,364 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", }, "Type": "AWS::IAM::Policy", }, + "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Read Uninstallable Report","States":{"Read Uninstallable Report":{"Next":"Has Packages?","Retry":[{"ErrorEquals":["Lambda.ClientExecutionTimeoutException","Lambda.ServiceException","Lambda.AWSLambdaException","Lambda.SdkClientException"],"IntervalSeconds":2,"MaxAttempts":6,"BackoffRate":2},{"ErrorEquals":["Lambda.Unknown"],"IntervalSeconds":2,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"Next":"No Report Found"}],"Type":"Task","ResultPath":"$.reportResponse","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::lambda:invoke","Parameters":{"FunctionName":"", + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + "","Payload":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","key":"uninstallable-objects/data.json"}}},"Has Packages?":{"Type":"Choice","Choices":[{"Variable":"$.reportResponse.Payload.packages[0]","IsPresent":true,"Next":"Process Each Package"}],"Default":"No Packages to Retry"},"No Packages to Retry":{"Type":"Succeed"},"Process Each Package":{"Type":"Map","ResultPath":null,"End":true,"ItemsPath":"$.reportResponse.Payload.packages","ItemProcessor":{"ProcessorConfig":{"Mode":"INLINE"},"StartAt":"Retry Package","States":{"Retry Package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"],"IntervalSeconds":60,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.ALL"],"ResultPath":"$.error","Next":"Package Retry Failed"}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","assembly":{"key.$":"States.Format('data/{}/v{}/assembly.json', $.packageName, $.packageVersion)"},"metadata":{"key.$":"States.Format('data/{}/v{}/metadata.json', $.packageName, $.packageVersion)"},"package":{"key.$":"States.Format('data/{}/v{}/package.tgz', $.packageName, $.packageVersion)"}},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ""}},"Package Retry Failed":{"Type":"Pass","Parameters":{"package.$":"$.originalPackage","prefix.$":"States.Format('data/{}/v{}', $.packageName, $.packageVersion)","error.$":"$.error"},"End":true}}}},"No Report Found":{"Type":"Fail","Error":"NoReportFound","Cause":"Uninstallable packages report not found at uninstallable-objects/data.json"}},"TimeoutSeconds":21600}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + "Arn", + ], + }, + "StateMachineName": "RetryUninstallablePackages", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2": { + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "fb54708aff141c6bb8f32a52c2c3ae5928620794390e5ea974fcb07cc588ffef.zip", + }, + "Description": "backend/orchestration/read-uninstallable-report.lambda.ts", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + }, + "Type": "AWS::Lambda::Function", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionLogRetentionBDF7ED83": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + }, + ], + ], + }, + "RetentionInDays": 90, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestration39161A46", + }, + }, + { + "Action": [ + "states:DescribeExecution", + "states:StopExecution", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":states:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":execution:", + { + "Fn::Select": [ + 6, + { + "Fn::Split": [ + ":", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ], + }, + ], + }, + "*", + ], + ], + }, + }, + { + "Action": [ + "events:PutTargets", + "events:PutRule", + "events:DescribeRule", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":events:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":rule/StepFunctionsGetEventsForStepFunctionsExecutionRule", + ], + ], + }, + }, + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, "ConstructHubOrchestrationRoleDefaultPolicyEACD181F": { "Properties": { "PolicyDocument": { @@ -14650,6 +15016,10 @@ def sort_filter_rules(json_obj): { "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254", }, + ")\\n[button:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, ")"}},{"type":"metric","width":12,"height":6,"x":0,"y":99,"properties":{"view":"timeSeries","title":"State Machine Executions","region":"", { "Ref": "AWS::Region", @@ -14842,7 +15212,11 @@ def sort_filter_rules(json_obj): "Arn", ], }, - "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", + "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n\\n[button:primary:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, + ")\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", { "Fn::GetAtt": [ "PackageVersionsTableWidgetHandler5fa848259c1d5e388c0df69f05c016dfBE2C27C2", @@ -20851,6 +21225,364 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", }, "Type": "AWS::IAM::Policy", }, + "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Read Uninstallable Report","States":{"Read Uninstallable Report":{"Next":"Has Packages?","Retry":[{"ErrorEquals":["Lambda.ClientExecutionTimeoutException","Lambda.ServiceException","Lambda.AWSLambdaException","Lambda.SdkClientException"],"IntervalSeconds":2,"MaxAttempts":6,"BackoffRate":2},{"ErrorEquals":["Lambda.Unknown"],"IntervalSeconds":2,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"Next":"No Report Found"}],"Type":"Task","ResultPath":"$.reportResponse","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::lambda:invoke","Parameters":{"FunctionName":"", + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + "","Payload":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","key":"uninstallable-objects/data.json"}}},"Has Packages?":{"Type":"Choice","Choices":[{"Variable":"$.reportResponse.Payload.packages[0]","IsPresent":true,"Next":"Process Each Package"}],"Default":"No Packages to Retry"},"No Packages to Retry":{"Type":"Succeed"},"Process Each Package":{"Type":"Map","ResultPath":null,"End":true,"ItemsPath":"$.reportResponse.Payload.packages","ItemProcessor":{"ProcessorConfig":{"Mode":"INLINE"},"StartAt":"Retry Package","States":{"Retry Package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"],"IntervalSeconds":60,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.ALL"],"ResultPath":"$.error","Next":"Package Retry Failed"}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","assembly":{"key.$":"States.Format('data/{}/v{}/assembly.json', $.packageName, $.packageVersion)"},"metadata":{"key.$":"States.Format('data/{}/v{}/metadata.json', $.packageName, $.packageVersion)"},"package":{"key.$":"States.Format('data/{}/v{}/package.tgz', $.packageName, $.packageVersion)"}},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ""}},"Package Retry Failed":{"Type":"Pass","Parameters":{"package.$":"$.originalPackage","prefix.$":"States.Format('data/{}/v{}', $.packageName, $.packageVersion)","error.$":"$.error"},"End":true}}}},"No Report Found":{"Type":"Fail","Error":"NoReportFound","Cause":"Uninstallable packages report not found at uninstallable-objects/data.json"}},"TimeoutSeconds":21600}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + "Arn", + ], + }, + "StateMachineName": "RetryUninstallablePackages", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2": { + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "fb54708aff141c6bb8f32a52c2c3ae5928620794390e5ea974fcb07cc588ffef.zip", + }, + "Description": "backend/orchestration/read-uninstallable-report.lambda.ts", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + }, + "Type": "AWS::Lambda::Function", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionLogRetentionBDF7ED83": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + }, + ], + ], + }, + "RetentionInDays": 90, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestration39161A46", + }, + }, + { + "Action": [ + "states:DescribeExecution", + "states:StopExecution", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":states:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":execution:", + { + "Fn::Select": [ + 6, + { + "Fn::Split": [ + ":", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ], + }, + ], + }, + "*", + ], + ], + }, + }, + { + "Action": [ + "events:PutTargets", + "events:PutRule", + "events:DescribeRule", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":events:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":rule/StepFunctionsGetEventsForStepFunctionsExecutionRule", + ], + ], + }, + }, + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, "ConstructHubOrchestrationRoleDefaultPolicyEACD181F": { "Properties": { "PolicyDocument": { @@ -28686,6 +29418,10 @@ def sort_filter_rules(json_obj): { "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254", }, + ")\\n[button:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, ")"}},{"type":"metric","width":12,"height":6,"x":0,"y":99,"properties":{"view":"timeSeries","title":"State Machine Executions","region":"", { "Ref": "AWS::Region", @@ -28878,7 +29614,11 @@ def sort_filter_rules(json_obj): "Arn", ], }, - "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", + "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n\\n[button:primary:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, + ")\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", { "Fn::GetAtt": [ "PackageVersionsTableWidgetHandler5fa848259c1d5e388c0df69f05c016dfBE2C27C2", @@ -34586,6 +35326,364 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", }, "Type": "AWS::IAM::Policy", }, + "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Read Uninstallable Report","States":{"Read Uninstallable Report":{"Next":"Has Packages?","Retry":[{"ErrorEquals":["Lambda.ClientExecutionTimeoutException","Lambda.ServiceException","Lambda.AWSLambdaException","Lambda.SdkClientException"],"IntervalSeconds":2,"MaxAttempts":6,"BackoffRate":2},{"ErrorEquals":["Lambda.Unknown"],"IntervalSeconds":2,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"Next":"No Report Found"}],"Type":"Task","ResultPath":"$.reportResponse","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::lambda:invoke","Parameters":{"FunctionName":"", + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + "","Payload":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","key":"uninstallable-objects/data.json"}}},"Has Packages?":{"Type":"Choice","Choices":[{"Variable":"$.reportResponse.Payload.packages[0]","IsPresent":true,"Next":"Process Each Package"}],"Default":"No Packages to Retry"},"No Packages to Retry":{"Type":"Succeed"},"Process Each Package":{"Type":"Map","ResultPath":null,"End":true,"ItemsPath":"$.reportResponse.Payload.packages","ItemProcessor":{"ProcessorConfig":{"Mode":"INLINE"},"StartAt":"Retry Package","States":{"Retry Package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"],"IntervalSeconds":60,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.ALL"],"ResultPath":"$.error","Next":"Package Retry Failed"}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","assembly":{"key.$":"States.Format('data/{}/v{}/assembly.json', $.packageName, $.packageVersion)"},"metadata":{"key.$":"States.Format('data/{}/v{}/metadata.json', $.packageName, $.packageVersion)"},"package":{"key.$":"States.Format('data/{}/v{}/package.tgz', $.packageName, $.packageVersion)"}},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ""}},"Package Retry Failed":{"Type":"Pass","Parameters":{"package.$":"$.originalPackage","prefix.$":"States.Format('data/{}/v{}', $.packageName, $.packageVersion)","error.$":"$.error"},"End":true}}}},"No Report Found":{"Type":"Fail","Error":"NoReportFound","Cause":"Uninstallable packages report not found at uninstallable-objects/data.json"}},"TimeoutSeconds":21600}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + "Arn", + ], + }, + "StateMachineName": "RetryUninstallablePackages", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2": { + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "fb54708aff141c6bb8f32a52c2c3ae5928620794390e5ea974fcb07cc588ffef.zip", + }, + "Description": "backend/orchestration/read-uninstallable-report.lambda.ts", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + }, + "Type": "AWS::Lambda::Function", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionLogRetentionBDF7ED83": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + }, + ], + ], + }, + "RetentionInDays": 90, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestration39161A46", + }, + }, + { + "Action": [ + "states:DescribeExecution", + "states:StopExecution", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":states:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":execution:", + { + "Fn::Select": [ + 6, + { + "Fn::Split": [ + ":", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ], + }, + ], + }, + "*", + ], + ], + }, + }, + { + "Action": [ + "events:PutTargets", + "events:PutRule", + "events:DescribeRule", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":events:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":rule/StepFunctionsGetEventsForStepFunctionsExecutionRule", + ], + ], + }, + }, + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, "ConstructHubOrchestrationRoleDefaultPolicyEACD181F": { "Properties": { "PolicyDocument": { @@ -42496,6 +43594,10 @@ def sort_filter_rules(json_obj): { "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254", }, + ")\\n[button:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, ")"}},{"type":"metric","width":12,"height":6,"x":0,"y":99,"properties":{"view":"timeSeries","title":"State Machine Executions","region":"", { "Ref": "AWS::Region", @@ -42688,7 +43790,11 @@ def sort_filter_rules(json_obj): "Arn", ], }, - "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", + "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n\\n[button:primary:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, + ")\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", { "Fn::GetAtt": [ "PackageVersionsTableWidgetHandler5fa848259c1d5e388c0df69f05c016dfBE2C27C2", @@ -47975,235 +49081,577 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", }, "Type": "AWS::IAM::Role", }, - "ConstructHubOrchestrationRedriveServiceRoleDefaultPolicyC018F436": { + "ConstructHubOrchestrationRedriveServiceRoleDefaultPolicyC018F436": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestration39161A46", + }, + }, + { + "Action": [ + "sqs:ReceiveMessage", + "sqs:ChangeMessageVisibility", + "sqs:GetQueueUrl", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationDLQ9C6D9BD4", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRedriveServiceRoleDefaultPolicyC018F436", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRedriveServiceRoleB84EFF33", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRegenerateAllDocumentationRoleDefaultPolicy2F4FBD86", + "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Get prefix page","States":{"Get prefix page":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Next prefixes page"}],"Default":"First prefix page"},"Has more prefixes?":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Get prefix page"}],"Default":"Done"},"For each prefix":{"Type":"Map","ResultPath":null,"Next":"Has more prefixes?","ItemsPath":"$.response.CommonPrefixes","Iterator":{"StartAt":"Is this a @scope-- prefix?","States":{"Is this a @scope-- prefix?":{"Type":"Choice","Choices":[{"Variable":"$.Prefix","StringMatches":"data/@*","Next":"Get @scope page"}],"Default":"Process unscoped package"},"Process unscoped package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"]}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"Prefix.$":"$.Prefix","AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$":"$$.Execution.Id"},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", + }, + ""}},"Get @scope page":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Next @scope page"}],"Default":"First @scope page"},"Has more packages?":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Get @scope page"}],"Default":"All Done"},"For each @scope--pkg":{"Type":"Map","ResultPath":null,"Next":"Has more packages?","ItemsPath":"$.response.CommonPrefixes","Iterator":{"StartAt":"Process scoped package","States":{"Process scoped package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"]}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"Prefix.$":"$.Prefix","AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$":"$$.Execution.Id"},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", + }, + ""}}}}},"First @scope page":{"Next":"For each @scope--pkg","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","Delimiter":"/","Prefix.$":"$.Prefix"}},"Next @scope page":{"Next":"For each @scope--pkg","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","ContinuationToken.$":"$.response.NextContinuationToken","Delimiter":"/","Prefix.$":"$.Prefix"}},"All Done":{"Type":"Succeed"}}}},"First prefix page":{"Next":"For each prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","Delimiter":"/","Prefix":"data/"}},"Next prefixes page":{"Next":"For each prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","ContinuationToken.$":"$.response.NextContinuationToken","Delimiter":"/","Prefix":"data/"}},"Done":{"Type":"Succeed"}},"TimeoutSeconds":14400}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F", + "Arn", + ], + }, + "StateMachineName": "Test.ConstructHub.Orchestration.RegenerateAllDocumentation", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleDefaultPolicy001A4726", + "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Get package versions page","States":{"Get package versions page":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Next versions page"}],"Default":"First versions page"},"Has more versions?":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Get package versions page"}],"Default":"Success"},"For each key prefix":{"Type":"Map","ResultPath":null,"Next":"Has more versions?","ItemsPath":"$.response.CommonPrefixes","Iterator":{"StartAt":"Start Orchestration Workflow","States":{"Start Orchestration Workflow":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"]}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"ResultPath":"$.error","Next":"StateMachine Success"}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution","Parameters":{"Input":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","assembly":{"key.$":"States.Format('{}assembly.json', $.Prefix)"},"metadata":{"key.$":"States.Format('{}metadata.json', $.Prefix)"},"package":{"key.$":"States.Format('{}package.tgz', $.Prefix)"},"AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$":"$$.Execution.Id"},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ""}},"StateMachine Success":{"Type":"Succeed"}}}},"First versions page":{"Next":"For each key prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","Delimiter":"/","Prefix.$":"$.Prefix"}},"Next versions page":{"Next":"For each key prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","ContinuationToken.$":"$.response.NextContinuationToken","Delimiter":"/","Prefix.$":"$.Prefix"}},"Success":{"Type":"Succeed"}},"TimeoutSeconds":3600}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73", + "Arn", + ], + }, + "StateMachineName": "ReprocessDocumentationPerPackage", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleDefaultPolicy001A4726": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:ListBucket", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestration39161A46", + }, + }, + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleDefaultPolicy001A4726", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRegenerateAllDocumentationRoleDefaultPolicy2F4FBD86": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:ListBucket", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", + }, + }, + { + "Action": [ + "states:DescribeExecution", + "states:StopExecution", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":states:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":execution:", + { + "Fn::Select": [ + 6, + { + "Fn::Split": [ + ":", + { + "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", + }, + ], + }, + ], + }, + "*", + ], + ], + }, + }, + { + "Action": [ + "events:PutTargets", + "events:PutRule", + "events:DescribeRule", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":events:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":rule/StepFunctionsGetEventsForStepFunctionsExecutionRule", + ], + ], + }, + }, + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRegenerateAllDocumentationRoleDefaultPolicy2F4FBD86", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Read Uninstallable Report","States":{"Read Uninstallable Report":{"Next":"Has Packages?","Retry":[{"ErrorEquals":["Lambda.ClientExecutionTimeoutException","Lambda.ServiceException","Lambda.AWSLambdaException","Lambda.SdkClientException"],"IntervalSeconds":2,"MaxAttempts":6,"BackoffRate":2},{"ErrorEquals":["Lambda.Unknown"],"IntervalSeconds":2,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"Next":"No Report Found"}],"Type":"Task","ResultPath":"$.reportResponse","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::lambda:invoke","Parameters":{"FunctionName":"", + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + "","Payload":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","key":"uninstallable-objects/data.json"}}},"Has Packages?":{"Type":"Choice","Choices":[{"Variable":"$.reportResponse.Payload.packages[0]","IsPresent":true,"Next":"Process Each Package"}],"Default":"No Packages to Retry"},"No Packages to Retry":{"Type":"Succeed"},"Process Each Package":{"Type":"Map","ResultPath":null,"End":true,"ItemsPath":"$.reportResponse.Payload.packages","ItemProcessor":{"ProcessorConfig":{"Mode":"INLINE"},"StartAt":"Retry Package","States":{"Retry Package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"],"IntervalSeconds":60,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.ALL"],"ResultPath":"$.error","Next":"Package Retry Failed"}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","assembly":{"key.$":"States.Format('data/{}/v{}/assembly.json', $.packageName, $.packageVersion)"},"metadata":{"key.$":"States.Format('data/{}/v{}/metadata.json', $.packageName, $.packageVersion)"},"package":{"key.$":"States.Format('data/{}/v{}/package.tgz', $.packageName, $.packageVersion)"}},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ""}},"Package Retry Failed":{"Type":"Pass","Parameters":{"package.$":"$.originalPackage","prefix.$":"States.Format('data/{}/v{}', $.packageName, $.packageVersion)","error.$":"$.error"},"End":true}}}},"No Report Found":{"Type":"Fail","Error":"NoReportFound","Cause":"Uninstallable packages report not found at uninstallable-objects/data.json"}},"TimeoutSeconds":21600}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + "Arn", + ], + }, + "StateMachineName": "RetryUninstallablePackages", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2": { + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "fb54708aff141c6bb8f32a52c2c3ae5928620794390e5ea974fcb07cc588ffef.zip", + }, + "Description": "backend/orchestration/read-uninstallable-report.lambda.ts", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + }, + "Type": "AWS::Lambda::Function", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionLogRetentionBDF7ED83": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + }, + ], + ], + }, + "RetentionInDays": 90, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73": { "Properties": { "PolicyDocument": { "Statement": [ - { - "Action": [ - "xray:PutTraceSegments", - "xray:PutTelemetryRecords", - ], - "Effect": "Allow", - "Resource": "*", - }, - { - "Action": "states:StartExecution", - "Effect": "Allow", - "Resource": { - "Ref": "ConstructHubOrchestration39161A46", - }, - }, - { - "Action": [ - "sqs:ReceiveMessage", - "sqs:ChangeMessageVisibility", - "sqs:GetQueueUrl", - "sqs:DeleteMessage", - "sqs:GetQueueAttributes", - ], - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ConstructHubOrchestrationDLQ9C6D9BD4", - "Arn", - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "ConstructHubOrchestrationRedriveServiceRoleDefaultPolicyC018F436", - "Roles": [ - { - "Ref": "ConstructHubOrchestrationRedriveServiceRoleB84EFF33", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254": { - "DeletionPolicy": "Delete", - "DependsOn": [ - "ConstructHubOrchestrationRegenerateAllDocumentationRoleDefaultPolicy2F4FBD86", - "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F", - ], - "Properties": { - "DefinitionString": { - "Fn::Join": [ - "", - [ - "{"StartAt":"Get prefix page","States":{"Get prefix page":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Next prefixes page"}],"Default":"First prefix page"},"Has more prefixes?":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Get prefix page"}],"Default":"Done"},"For each prefix":{"Type":"Map","ResultPath":null,"Next":"Has more prefixes?","ItemsPath":"$.response.CommonPrefixes","Iterator":{"StartAt":"Is this a @scope-- prefix?","States":{"Is this a @scope-- prefix?":{"Type":"Choice","Choices":[{"Variable":"$.Prefix","StringMatches":"data/@*","Next":"Get @scope page"}],"Default":"Process unscoped package"},"Process unscoped package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"]}],"Type":"Task","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::states:startExecution.sync:2","Parameters":{"Input":{"Prefix.$":"$.Prefix","AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$":"$$.Execution.Id"},"StateMachineArn":"", - { - "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", - }, - ""}},"Get @scope page":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Next @scope page"}],"Default":"First @scope page"},"Has more packages?":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Get @scope page"}],"Default":"All Done"},"For each @scope--pkg":{"Type":"Map","ResultPath":null,"Next":"Has more packages?","ItemsPath":"$.response.CommonPrefixes","Iterator":{"StartAt":"Process scoped package","States":{"Process scoped package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"]}],"Type":"Task","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::states:startExecution.sync:2","Parameters":{"Input":{"Prefix.$":"$.Prefix","AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$":"$$.Execution.Id"},"StateMachineArn":"", - { - "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", - }, - ""}}}}},"First @scope page":{"Next":"For each @scope--pkg","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", - { - "Ref": "ConstructHubPackageDataDC5EF35E", - }, - "","Delimiter":"/","Prefix.$":"$.Prefix"}},"Next @scope page":{"Next":"For each @scope--pkg","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", - { - "Ref": "ConstructHubPackageDataDC5EF35E", - }, - "","ContinuationToken.$":"$.response.NextContinuationToken","Delimiter":"/","Prefix.$":"$.Prefix"}},"All Done":{"Type":"Succeed"}}}},"First prefix page":{"Next":"For each prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", - { - "Ref": "ConstructHubPackageDataDC5EF35E", - }, - "","Delimiter":"/","Prefix":"data/"}},"Next prefixes page":{"Next":"For each prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", - { - "Ref": "ConstructHubPackageDataDC5EF35E", - }, - "","ContinuationToken.$":"$.response.NextContinuationToken","Delimiter":"/","Prefix":"data/"}},"Done":{"Type":"Succeed"}},"TimeoutSeconds":14400}", - ], - ], - }, - "RoleArn": { - "Fn::GetAtt": [ - "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F", - "Arn", - ], - }, - "StateMachineName": "Test.ConstructHub.Orchestration.RegenerateAllDocumentation", - "TracingConfiguration": { - "Enabled": true, - }, - }, - "Type": "AWS::StepFunctions::StateMachine", - "UpdateReplacePolicy": "Delete", - }, - "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7": { - "DeletionPolicy": "Delete", - "DependsOn": [ - "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleDefaultPolicy001A4726", - "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73", - ], - "Properties": { - "DefinitionString": { - "Fn::Join": [ - "", - [ - "{"StartAt":"Get package versions page","States":{"Get package versions page":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Next versions page"}],"Default":"First versions page"},"Has more versions?":{"Type":"Choice","Choices":[{"Variable":"$.response.NextContinuationToken","IsPresent":true,"Next":"Get package versions page"}],"Default":"Success"},"For each key prefix":{"Type":"Map","ResultPath":null,"Next":"Has more versions?","ItemsPath":"$.response.CommonPrefixes","Iterator":{"StartAt":"Start Orchestration Workflow","States":{"Start Orchestration Workflow":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"]}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"ResultPath":"$.error","Next":"StateMachine Success"}],"Type":"Task","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::states:startExecution","Parameters":{"Input":{"bucket":"", - { - "Ref": "ConstructHubPackageDataDC5EF35E", - }, - "","assembly":{"key.$":"States.Format('{}assembly.json', $.Prefix)"},"metadata":{"key.$":"States.Format('{}metadata.json', $.Prefix)"},"package":{"key.$":"States.Format('{}package.tgz', $.Prefix)"},"AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$":"$$.Execution.Id"},"StateMachineArn":"", - { - "Ref": "ConstructHubOrchestration39161A46", - }, - ""}},"StateMachine Success":{"Type":"Succeed"}}}},"First versions page":{"Next":"For each key prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", - { - "Ref": "ConstructHubPackageDataDC5EF35E", - }, - "","Delimiter":"/","Prefix.$":"$.Prefix"}},"Next versions page":{"Next":"For each key prefix","Retry":[{"ErrorEquals":["S3.SdkClientException"]}],"Type":"Task","ResultPath":"$.response","Resource":"arn:", - { - "Ref": "AWS::Partition", - }, - ":states:::aws-sdk:s3:listObjectsV2","Parameters":{"Bucket":"", - { - "Ref": "ConstructHubPackageDataDC5EF35E", - }, - "","ContinuationToken.$":"$.response.NextContinuationToken","Delimiter":"/","Prefix.$":"$.Prefix"}},"Success":{"Type":"Succeed"}},"TimeoutSeconds":3600}", - ], - ], - }, - "RoleArn": { - "Fn::GetAtt": [ - "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73", - "Arn", - ], - }, - "StateMachineName": "ReprocessDocumentationPerPackage", - "TracingConfiguration": { - "Enabled": true, - }, - }, - "Type": "AWS::StepFunctions::StateMachine", - "UpdateReplacePolicy": "Delete", - }, - "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "states.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - }, - "Type": "AWS::IAM::Role", - }, - "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleDefaultPolicy001A4726": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "s3:ListBucket", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ConstructHubPackageDataDC5EF35E", - "Arn", - ], - }, - }, - { - "Action": "states:StartExecution", - "Effect": "Allow", - "Resource": { - "Ref": "ConstructHubOrchestration39161A46", - }, - }, - { - "Action": [ - "xray:PutTraceSegments", - "xray:PutTelemetryRecords", - "xray:GetSamplingRules", - "xray:GetSamplingTargets", - ], - "Effect": "Allow", - "Resource": "*", - }, { "Action": [ "s3:GetObject*", @@ -48237,16 +49685,16 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Version": "2012-10-17", }, - "PolicyName": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleDefaultPolicy001A4726", + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", "Roles": [ { - "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackageRoleD7CCFA73", + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", }, ], }, "Type": "AWS::IAM::Policy", }, - "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F": { + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573": { "Properties": { "AssumeRolePolicyDocument": { "Statement": [ @@ -48263,25 +49711,41 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", }, "Type": "AWS::IAM::Role", }, - "ConstructHubOrchestrationRegenerateAllDocumentationRoleDefaultPolicy2F4FBD86": { + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523": { "Properties": { "PolicyDocument": { "Statement": [ { - "Action": "s3:ListBucket", + "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "ConstructHubPackageDataDC5EF35E", - "Arn", - ], - }, + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], }, { "Action": "states:StartExecution", "Effect": "Allow", "Resource": { - "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", + "Ref": "ConstructHubOrchestration39161A46", }, }, { @@ -48314,7 +49778,7 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", "Fn::Split": [ ":", { - "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationPerPackage9CF0FFB7", + "Ref": "ConstructHubOrchestration39161A46", }, ], }, @@ -48396,10 +49860,10 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Version": "2012-10-17", }, - "PolicyName": "ConstructHubOrchestrationRegenerateAllDocumentationRoleDefaultPolicy2F4FBD86", + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", "Roles": [ { - "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationRole1C7D3B5F", + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", }, ], }, @@ -56489,6 +57953,10 @@ def sort_filter_rules(json_obj): { "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254", }, + ")\\n[button:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, ")"}},{"type":"metric","width":12,"height":6,"x":0,"y":99,"properties":{"view":"timeSeries","title":"State Machine Executions","region":"", { "Ref": "AWS::Region", @@ -56681,7 +58149,11 @@ def sort_filter_rules(json_obj): "Arn", ], }, - "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", + "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n\\n[button:primary:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, + ")\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", { "Fn::GetAtt": [ "PackageVersionsTableWidgetHandler5fa848259c1d5e388c0df69f05c016dfBE2C27C2", @@ -62137,6 +63609,364 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", }, "Type": "AWS::IAM::Policy", }, + "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Read Uninstallable Report","States":{"Read Uninstallable Report":{"Next":"Has Packages?","Retry":[{"ErrorEquals":["Lambda.ClientExecutionTimeoutException","Lambda.ServiceException","Lambda.AWSLambdaException","Lambda.SdkClientException"],"IntervalSeconds":2,"MaxAttempts":6,"BackoffRate":2},{"ErrorEquals":["Lambda.Unknown"],"IntervalSeconds":2,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"Next":"No Report Found"}],"Type":"Task","ResultPath":"$.reportResponse","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::lambda:invoke","Parameters":{"FunctionName":"", + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + "","Payload":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","key":"uninstallable-objects/data.json"}}},"Has Packages?":{"Type":"Choice","Choices":[{"Variable":"$.reportResponse.Payload.packages[0]","IsPresent":true,"Next":"Process Each Package"}],"Default":"No Packages to Retry"},"No Packages to Retry":{"Type":"Succeed"},"Process Each Package":{"Type":"Map","ResultPath":null,"End":true,"ItemsPath":"$.reportResponse.Payload.packages","ItemProcessor":{"ProcessorConfig":{"Mode":"INLINE"},"StartAt":"Retry Package","States":{"Retry Package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"],"IntervalSeconds":60,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.ALL"],"ResultPath":"$.error","Next":"Package Retry Failed"}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","assembly":{"key.$":"States.Format('data/{}/v{}/assembly.json', $.packageName, $.packageVersion)"},"metadata":{"key.$":"States.Format('data/{}/v{}/metadata.json', $.packageName, $.packageVersion)"},"package":{"key.$":"States.Format('data/{}/v{}/package.tgz', $.packageName, $.packageVersion)"}},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ""}},"Package Retry Failed":{"Type":"Pass","Parameters":{"package.$":"$.originalPackage","prefix.$":"States.Format('data/{}/v{}', $.packageName, $.packageVersion)","error.$":"$.error"},"End":true}}}},"No Report Found":{"Type":"Fail","Error":"NoReportFound","Cause":"Uninstallable packages report not found at uninstallable-objects/data.json"}},"TimeoutSeconds":21600}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + "Arn", + ], + }, + "StateMachineName": "RetryUninstallablePackages", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2": { + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "fb54708aff141c6bb8f32a52c2c3ae5928620794390e5ea974fcb07cc588ffef.zip", + }, + "Description": "backend/orchestration/read-uninstallable-report.lambda.ts", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + }, + "Type": "AWS::Lambda::Function", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionLogRetentionBDF7ED83": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + }, + ], + ], + }, + "RetentionInDays": 90, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestration39161A46", + }, + }, + { + "Action": [ + "states:DescribeExecution", + "states:StopExecution", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":states:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":execution:", + { + "Fn::Select": [ + 6, + { + "Fn::Split": [ + ":", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ], + }, + ], + }, + "*", + ], + ], + }, + }, + { + "Action": [ + "events:PutTargets", + "events:PutRule", + "events:DescribeRule", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":events:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":rule/StepFunctionsGetEventsForStepFunctionsExecutionRule", + ], + ], + }, + }, + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, "ConstructHubOrchestrationRoleDefaultPolicyEACD181F": { "DependsOn": [ "ConstructHubVPCIGW935F4C28", diff --git a/src/__tests__/backend/orchestration/read-uninstallable-report.lambda.test.ts b/src/__tests__/backend/orchestration/read-uninstallable-report.lambda.test.ts new file mode 100644 index 000000000..69d42f351 --- /dev/null +++ b/src/__tests__/backend/orchestration/read-uninstallable-report.lambda.test.ts @@ -0,0 +1,62 @@ +import { GetObjectCommand } from '@aws-sdk/client-s3'; +import { mockClient } from 'aws-sdk-client-mock'; +import { handler } from '../../../backend/orchestration/read-uninstallable-report.lambda'; +import { S3_CLIENT } from '../../../backend/shared/aws.lambda-shared'; + +const s3Mock = mockClient(S3_CLIENT); + +beforeEach(() => { + s3Mock.reset(); +}); + +test('reads and decompresses uninstallable packages report', async () => { + const rawPackages = ['package1@1.0.0', '@aws-cdk/core@2.0.0']; + const mockBody = { + transformToString: jest.fn().mockResolvedValue(JSON.stringify(rawPackages)), + }; + + s3Mock.on(GetObjectCommand).resolves({ + Body: mockBody as any, + ContentEncoding: undefined, + }); + + const result = await handler({ + bucket: 'test-bucket', + key: 'uninstallable-objects/data.json', + }); + + expect(result).toEqual({ + packages: [ + { + originalPackage: 'package1@1.0.0', + packageName: 'package1', + packageVersion: '1.0.0', + }, + { + originalPackage: '@aws-cdk/core@2.0.0', + packageName: '@aws-cdk/core', + packageVersion: '2.0.0', + }, + ], + }); + expect(s3Mock.calls()).toHaveLength(1); + expect(s3Mock.call(0).args[0].input).toEqual({ + Bucket: 'test-bucket', + Key: 'uninstallable-objects/data.json', + }); +}); + +test('throws error when object not found', async () => { + s3Mock.on(GetObjectCommand).resolves({ + Body: undefined, + }); + + await expect( + handler({ + bucket: 'test-bucket', + key: 'uninstallable-objects/data.json', + }) + ).rejects.toThrow( + 'Object not found: s3://test-bucket/uninstallable-objects/data.json' + ); +}); diff --git a/src/__tests__/backend/orchestration/retry-uninstallable-packages.test.ts b/src/__tests__/backend/orchestration/retry-uninstallable-packages.test.ts new file mode 100644 index 000000000..613da14a6 --- /dev/null +++ b/src/__tests__/backend/orchestration/retry-uninstallable-packages.test.ts @@ -0,0 +1,37 @@ +import { Stack } from 'aws-cdk-lib'; +import { Template } from 'aws-cdk-lib/assertions'; +import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; +import { RetryUninstallablePackages } from '../../../backend/orchestration/retry-uninstallable-packages'; + +test('creates required resources', () => { + const stack = new Stack(); + const bucket = new s3.Bucket(stack, 'TestBucket'); + const orchestrationStateMachine = new sfn.StateMachine( + stack, + 'OrchestrationStateMachine', + { + definition: new sfn.Pass(stack, 'TestPass'), + } + ); + + new RetryUninstallablePackages(stack, 'RetryUninstallablePackages', { + bucket, + orchestrationStateMachine, + }); + + const template = Template.fromStack(stack); + + // Verify state machine is created with correct name + template.hasResourceProperties('AWS::StepFunctions::StateMachine', { + StateMachineName: 'RetryUninstallablePackages', + }); + + // Verify Lambda function is created + template.hasResourceProperties('AWS::Lambda::Function', { + Runtime: 'nodejs22.x', + }); + + // Verify IAM policies exist + template.resourceCountIs('AWS::IAM::Policy', 3); +}); diff --git a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap index 675d860ca..0b6ec12e8 100644 --- a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap +++ b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap @@ -988,6 +988,10 @@ def sort_filter_rules(json_obj): { "Ref": "ConstructHubOrchestrationRegenerateAllDocumentationE9FAB254", }, + ")\\n[button:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, ")"}},{"type":"metric","width":12,"height":6,"x":0,"y":99,"properties":{"view":"timeSeries","title":"State Machine Executions","region":"", { "Ref": "AWS::Region", @@ -1253,7 +1257,11 @@ def sort_filter_rules(json_obj): "Arn", ], }, - "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", + "","params":{"key":"uninstallable-objects/data.json","description":"These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.\\n\\nThe specific error can be found in the package directory inside a file named 'uninstallable'\\n\\n[button:primary:Retry Uninstallable Packages](/states/home#/statemachines/view/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3", + }, + ")\\n"},"title":"Package Versions Report | Uninstallable","updateOn":{"refresh":true,"resize":false,"timeRange":false}}},{"type":"custom","width":24,"height":6,"x":0,"y":6,"properties":{"endpoint":"", { "Fn::GetAtt": [ "PackageVersionsTableWidgetHandler5fa848259c1d5e388c0df69f05c016dfBE2C27C2", @@ -7042,6 +7050,364 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", }, "Type": "AWS::IAM::Policy", }, + "ConstructHubOrchestrationRetryUninstallablePackagesA408F9B3": { + "DeletionPolicy": "Delete", + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + ], + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{"StartAt":"Read Uninstallable Report","States":{"Read Uninstallable Report":{"Next":"Has Packages?","Retry":[{"ErrorEquals":["Lambda.ClientExecutionTimeoutException","Lambda.ServiceException","Lambda.AWSLambdaException","Lambda.SdkClientException"],"IntervalSeconds":2,"MaxAttempts":6,"BackoffRate":2},{"ErrorEquals":["Lambda.Unknown"],"IntervalSeconds":2,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.TaskFailed"],"Next":"No Report Found"}],"Type":"Task","ResultPath":"$.reportResponse","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::lambda:invoke","Parameters":{"FunctionName":"", + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + "","Payload":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","key":"uninstallable-objects/data.json"}}},"Has Packages?":{"Type":"Choice","Choices":[{"Variable":"$.reportResponse.Payload.packages[0]","IsPresent":true,"Next":"Process Each Package"}],"Default":"No Packages to Retry"},"No Packages to Retry":{"Type":"Succeed"},"Process Each Package":{"Type":"Map","ResultPath":null,"End":true,"ItemsPath":"$.reportResponse.Payload.packages","ItemProcessor":{"ProcessorConfig":{"Mode":"INLINE"},"StartAt":"Retry Package","States":{"Retry Package":{"End":true,"Retry":[{"ErrorEquals":["StepFunctions.ExecutionLimitExceeded"],"IntervalSeconds":60,"MaxAttempts":3,"BackoffRate":2}],"Catch":[{"ErrorEquals":["States.ALL"],"ResultPath":"$.error","Next":"Package Retry Failed"}],"Type":"Task","Resource":"arn:", + { + "Ref": "AWS::Partition", + }, + ":states:::states:startExecution.sync:2","Parameters":{"Input":{"bucket":"", + { + "Ref": "ConstructHubPackageDataDC5EF35E", + }, + "","assembly":{"key.$":"States.Format('data/{}/v{}/assembly.json', $.packageName, $.packageVersion)"},"metadata":{"key.$":"States.Format('data/{}/v{}/metadata.json', $.packageName, $.packageVersion)"},"package":{"key.$":"States.Format('data/{}/v{}/package.tgz', $.packageName, $.packageVersion)"}},"StateMachineArn":"", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ""}},"Package Retry Failed":{"Type":"Pass","Parameters":{"package.$":"$.originalPackage","prefix.$":"States.Format('data/{}/v{}', $.packageName, $.packageVersion)","error.$":"$.error"},"End":true}}}},"No Report Found":{"Type":"Fail","Error":"NoReportFound","Cause":"Uninstallable packages report not found at uninstallable-objects/data.json"}},"TimeoutSeconds":21600}", + ], + ], + }, + "RoleArn": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + "Arn", + ], + }, + "StateMachineName": "RetryUninstallablePackages", + "TracingConfiguration": { + "Enabled": true, + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + "UpdateReplacePolicy": "Delete", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2": { + "DependsOn": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "fb54708aff141c6bb8f32a52c2c3ae5928620794390e5ea974fcb07cc588ffef.zip", + }, + "Description": "backend/orchestration/read-uninstallable-report.lambda.ts", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + "Arn", + ], + }, + "Runtime": "nodejs22.x", + }, + "Type": "AWS::Lambda::Function", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionLogRetentionBDF7ED83": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + }, + ], + ], + }, + "RetentionInDays": 90, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRoleDefaultPolicyCAAF8F73", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionServiceRole528C403B", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubOrchestrationRetryUninstallablePackagesReadReportFunctionF9851BD2", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": { + "Ref": "ConstructHubOrchestration39161A46", + }, + }, + { + "Action": [ + "states:DescribeExecution", + "states:StopExecution", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":states:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":execution:", + { + "Fn::Select": [ + 6, + { + "Fn::Split": [ + ":", + { + "Ref": "ConstructHubOrchestration39161A46", + }, + ], + }, + ], + }, + "*", + ], + ], + }, + }, + { + "Action": [ + "events:PutTargets", + "events:PutRule", + "events:DescribeRule", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":events:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":rule/StepFunctionsGetEventsForStepFunctionsExecutionRule", + ], + ], + }, + }, + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + ], + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ConstructHubPackageDataDC5EF35E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "ConstructHubOrchestrationRetryUninstallablePackagesRoleDefaultPolicy7CB8A523", + "Roles": [ + { + "Ref": "ConstructHubOrchestrationRetryUninstallablePackagesRole380D2573", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, "ConstructHubOrchestrationRoleDefaultPolicyEACD181F": { "Properties": { "PolicyDocument": { diff --git a/src/backend-dashboard.ts b/src/backend-dashboard.ts index cf67f4919..6f835ae0c 100644 --- a/src/backend-dashboard.ts +++ b/src/backend-dashboard.ts @@ -68,6 +68,10 @@ export class BackendDashboard extends Construct { "These packages could not be installed. Note that currently they will also appear in the 'missing' documentation reports.", '', "The specific error can be found in the package directory inside a file named 'uninstallable'", + '', + `[button:primary:Retry Uninstallable Packages](${stateMachineUrl( + props.orchestration.retryUninstallablePackages + )})`, ].join('\n'), bucket: props.packageData, key: UNINSTALLABLE_PACKAGES_REPORT, @@ -327,6 +331,9 @@ export class BackendDashboard extends Construct { `[button:Regenerate All Documentation](${stateMachineUrl( props.orchestration.regenerateAllDocumentation )})`, + `[button:Retry Uninstallable Packages](${stateMachineUrl( + props.orchestration.retryUninstallablePackages + )})`, ].join('\n'), }), ], diff --git a/src/backend/orchestration/index.ts b/src/backend/orchestration/index.ts index 7664f2afa..fcb86ac69 100644 --- a/src/backend/orchestration/index.ts +++ b/src/backend/orchestration/index.ts @@ -31,6 +31,8 @@ import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'; import { Construct } from 'constructs'; import { NeedsCatalogUpdate } from './needs-catalog-update'; import { RedriveStateMachine } from './redrive-state-machine'; +import { RetryUninstallablePackages } from './retry-uninstallable-packages'; +import { AlarmSeverities, AlarmSeverity } from '../../api'; import { Repository } from '../../codeartifact/repository'; import { sqsQueueUrl, stateMachineUrl } from '../../deep-link'; import { Monitoring, addAlarm } from '../../monitoring'; @@ -50,7 +52,6 @@ import { UNPROCESSABLE_PACKAGE_ERROR_NAME, } from '../shared/constants'; import { Transliterator, TransliteratorVpcEndpoints } from '../transliterator'; -import { AlarmSeverities, AlarmSeverity } from '../../api'; const REPROCESS_PER_PACKAGE_STATE_MACHINE_NAME = 'ReprocessDocumentationPerPackage'; @@ -197,6 +198,11 @@ export class Orchestration extends Construct { */ public readonly regenerateAllDocumentationPerPackage: IStateMachine; + /** + * The state machine operators can use to retry processing uninstallable packages. + */ + public readonly retryUninstallablePackages: IStateMachine; + /** * The function that builds the catalog. */ @@ -479,8 +485,9 @@ export class Orchestration extends Construct { this.stateMachine .metricFailed() .createAlarm(this, 'OrchestrationFailed', { - alarmName: `${this.stateMachine.node.path}/${this.stateMachine.metricFailed().metricName - }`, + alarmName: `${this.stateMachine.node.path}/${ + this.stateMachine.metricFailed().metricName + }`, alarmDescription: [ 'Backend orchestration failed!', '', @@ -497,7 +504,8 @@ export class Orchestration extends Construct { threshold: 1, }), props.alarmSeverities?.backendOrchestrationFailed ?? AlarmSeverity.HIGH, - props.monitoring); + props.monitoring + ); props.monitoring.addHighSeverityAlarm( 'Execution Failure Rate above 75%', @@ -550,6 +558,17 @@ export class Orchestration extends Construct { this.regenerateAllDocumentationPerPackage = regenerateAllDocumentation.processPackageVersions; + // Create retry uninstallable packages workflow + const retryUninstallable = new RetryUninstallablePackages( + this, + 'RetryUninstallablePackages', + { + bucket: props.bucket, + orchestrationStateMachine: this.stateMachine, + } + ); + this.retryUninstallablePackages = retryUninstallable.stateMachine; + props.overviewDashboard.addConcurrentExecutionMetricToDashboard( needsCatalogUpdateFunction, 'NeedsCatalogUpdateLambda' diff --git a/src/backend/orchestration/read-uninstallable-report.lambda.ts b/src/backend/orchestration/read-uninstallable-report.lambda.ts new file mode 100644 index 000000000..ce1e885cb --- /dev/null +++ b/src/backend/orchestration/read-uninstallable-report.lambda.ts @@ -0,0 +1,59 @@ +import { GetObjectCommand } from '@aws-sdk/client-s3'; +import { S3_CLIENT } from '../shared/aws.lambda-shared'; +import { decompressContent } from '../shared/compress-content.lambda-shared'; + +export interface ReadUninstallableReportEvent { + readonly bucket: string; + readonly key: string; +} + +export interface PackageInfo { + readonly originalPackage: string; + readonly packageName: string; + readonly packageVersion: string; +} + +export interface ReadUninstallableReportResult { + readonly packages: PackageInfo[]; +} + +function parsePackageName(packageString: string): PackageInfo { + const lastAtIndex = packageString.lastIndexOf('@'); + if (lastAtIndex === -1) { + throw new Error(`Invalid package format: ${packageString}`); + } + + const packageName = packageString.substring(0, lastAtIndex); + const packageVersion = packageString.substring(lastAtIndex + 1); + + return { + originalPackage: packageString, + packageName, + packageVersion, + }; +} + +export async function handler( + event: ReadUninstallableReportEvent +): Promise { + const response = await S3_CLIENT.send( + new GetObjectCommand({ + Bucket: event.bucket, + Key: event.key, + }) + ); + + if (!response.Body) { + throw new Error(`Object not found: s3://${event.bucket}/${event.key}`); + } + + const decompressed = await decompressContent( + response.Body as any, + response.ContentEncoding + ); + + const rawPackages = JSON.parse(decompressed); + const packages = rawPackages.map(parsePackageName); + + return { packages }; +} diff --git a/src/backend/orchestration/read-uninstallable-report.ts b/src/backend/orchestration/read-uninstallable-report.ts new file mode 100644 index 000000000..fb09fe89c --- /dev/null +++ b/src/backend/orchestration/read-uninstallable-report.ts @@ -0,0 +1,20 @@ +// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". +import * as path from 'path'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import { Construct } from 'constructs'; + +export interface ReadUninstallableReportProps extends lambda.FunctionOptions { +} + +export class ReadUninstallableReport extends lambda.Function { + constructor(scope: Construct, id: string, props?: ReadUninstallableReportProps) { + super(scope, id, { + description: 'backend/orchestration/read-uninstallable-report.lambda.ts', + ...props, + architecture: lambda.Architecture.ARM_64, + runtime: lambda.Runtime.NODEJS_22_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(path.join(__dirname, '/read-uninstallable-report.lambda.bundle')), + }); + } +} \ No newline at end of file diff --git a/src/backend/orchestration/retry-uninstallable-packages.ts b/src/backend/orchestration/retry-uninstallable-packages.ts new file mode 100644 index 000000000..54f51285c --- /dev/null +++ b/src/backend/orchestration/retry-uninstallable-packages.ts @@ -0,0 +1,157 @@ +import { Duration } from 'aws-cdk-lib'; +import { RetentionDays } from 'aws-cdk-lib/aws-logs'; +import { IBucket } from 'aws-cdk-lib/aws-s3'; +import { + IStateMachine, + StateMachine, + Succeed, + Fail, + Pass, + Choice, + Condition, + Map, + JsonPath, + IntegrationPattern, + TaskInput, +} from 'aws-cdk-lib/aws-stepfunctions'; +import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'; +import { Construct } from 'constructs'; +import { ReadUninstallableReport } from './read-uninstallable-report'; + +export interface RetryUninstallablePackagesProps { + readonly bucket: IBucket; + readonly orchestrationStateMachine: IStateMachine; +} + +/** + * State machine that retries processing of uninstallable packages. + * + * This workflow: + * 1. Reads the uninstallable packages report + * 2. Triggers main orchestration for each package + * 3. Ends after processing all packages + */ +export class RetryUninstallablePackages extends Construct { + public readonly stateMachine: StateMachine; + + public constructor( + scope: Construct, + id: string, + props: RetryUninstallablePackagesProps + ) { + super(scope, id); + + const noReportFound = new Fail(this, 'No Report Found', { + error: 'NoReportFound', + cause: + 'Uninstallable packages report not found at uninstallable-objects/data.json', + }); + + const noPackagesToRetry = new Succeed(this, 'No Packages to Retry'); + + const readReportFunction = new ReadUninstallableReport( + this, + 'ReadReportFunction', + { + logRetention: RetentionDays.THREE_MONTHS, + } + ); + + props.bucket.grantRead(readReportFunction); + + const readReport = new tasks.LambdaInvoke( + this, + 'Read Uninstallable Report', + { + lambdaFunction: readReportFunction, + payload: TaskInput.fromObject({ + bucket: props.bucket.bucketName, + key: 'uninstallable-objects/data.json', + }), + resultPath: '$.reportResponse', + } + ); + + readReport.addRetry({ + errors: ['Lambda.Unknown'], + interval: Duration.seconds(2), + maxAttempts: 3, + backoffRate: 2.0, + }); + + readReport.addCatch(noReportFound, { + errors: ['States.TaskFailed'], + }); + + const packageRetryFailed = new Pass(this, 'Package Retry Failed', { + parameters: { + 'package.$': '$.originalPackage', + 'prefix.$': + "States.Format('data/{}/v{}', $.packageName, $.packageVersion)", + 'error.$': '$.error', + }, + }); + + const retryPackage = new tasks.StepFunctionsStartExecution( + this, + 'Retry Package', + { + stateMachine: props.orchestrationStateMachine, + integrationPattern: IntegrationPattern.RUN_JOB, + input: TaskInput.fromObject({ + bucket: props.bucket.bucketName, + assembly: { + 'key.$': + "States.Format('data/{}/v{}/assembly.json', $.packageName, $.packageVersion)", + }, + metadata: { + 'key.$': + "States.Format('data/{}/v{}/metadata.json', $.packageName, $.packageVersion)", + }, + package: { + 'key.$': + "States.Format('data/{}/v{}/package.tgz', $.packageName, $.packageVersion)", + }, + }), + } + ); + + retryPackage.addRetry({ + errors: ['StepFunctions.ExecutionLimitExceeded'], + interval: Duration.seconds(60), + maxAttempts: 3, + backoffRate: 2.0, + }); + + retryPackage.addCatch(packageRetryFailed, { + errors: ['States.ALL'], + resultPath: '$.error', + }); + + const processEachPackage = new Map(this, 'Process Each Package', { + itemsPath: JsonPath.stringAt('$.reportResponse.Payload.packages'), + resultPath: JsonPath.DISCARD, + }); + + processEachPackage.itemProcessor(retryPackage); + + const hasPackages = new Choice(this, 'Has Packages?') + .when( + Condition.isPresent('$.reportResponse.Payload.packages[0]'), + processEachPackage + ) + .otherwise(noPackagesToRetry); + + const definition = readReport.next(hasPackages); + + this.stateMachine = new StateMachine(this, 'Resource', { + definition, + stateMachineName: 'RetryUninstallablePackages', + timeout: Duration.hours(6), + tracingEnabled: true, + }); + + props.bucket.grantRead(this.stateMachine); + props.orchestrationStateMachine.grantStartExecution(this.stateMachine); + } +}