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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 61 additions & 11 deletions .github/workflows/monthly-capacity-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ permissions:
jobs:
generate-report:
runs-on: ubuntu-latest
environment: prod
environment: reporting

steps:
- name: Checkout code
Expand All @@ -26,26 +26,77 @@ jobs:
with:
python-version: "3.11"

- name: "Configure AWS Credentials"
# ----------------------------------------------------------------
# 1. Export PROD
# ----------------------------------------------------------------
- name: "Configure AWS Credentials (Prod)"
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role
role-to-assume: arn:aws:iam::${{ secrets.AWS_PROD_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role
aws-region: eu-west-2

- name: Generate dashboard report
- name: Export Dashboard (Prod)
run: |
chmod +x scripts/export_dashboard_image.sh
./scripts/export_dashboard_image.sh Demand_And_Capacity_Prod
./scripts/export_dashboard_image.sh Demand_And_Capacity_Prod Prod
env:
AWS_REGION: eu-west-2

# ----------------------------------------------------------------
# 2. Export PREPROD
# ----------------------------------------------------------------
- name: "Configure AWS Credentials (Preprod)"
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_PREPROD_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role
aws-region: eu-west-2

- name: Export Dashboard (Preprod)
run: ./scripts/export_dashboard_image.sh Demand_And_Capacity_Preprod Preprod
env:
AWS_REGION: eu-west-2

# ----------------------------------------------------------------
# 3. Export TEST
# ----------------------------------------------------------------
- name: "Configure AWS Credentials (Test)"
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_TEST_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role
aws-region: eu-west-2

- name: Export Dashboard (Test)
run: ./scripts/export_dashboard_image.sh Demand_And_Capacity_Test Test
env:
AWS_REGION: eu-west-2

# ----------------------------------------------------------------
# 4. Export DEV
# ----------------------------------------------------------------
- name: "Configure AWS Credentials (Dev)"
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_DEV_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role
aws-region: eu-west-2

- name: Export Dashboard (Dev)
run: ./scripts/export_dashboard_image.sh Demand_And_Capacity_Dev Dev
env:
AWS_REGION: eu-west-2

# ----------------------------------------------------------------
# Generate & Notify
# ----------------------------------------------------------------
- name: Generate Combined Report
run: python3 scripts/generate_dashboard_report.py --input dashboard_exports

- name: Upload report as artifact
uses: actions/upload-artifact@v5
with:
name: capacity-report
path: |
dashboard_exports/*.html
dashboard_exports/*.png
dashboard_exports/**/*.html
dashboard_exports/**/*.png
retention-days: 90

- name: Send to Slack
Expand All @@ -54,21 +105,20 @@ jobs:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_D_AND_C_WEBHOOK }}
run: |
# Get the latest HTML report
REPORT_FILE=$(ls -t dashboard_exports/dashboard_report_*.html | head -1)
REPORT_FILE=$(find dashboard_exports -name "dashboard_report_*.html" | head -n 1)
REPORT_NAME=$(basename "$REPORT_FILE")

# GitHub Actions URL
GITHUB_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"

# Send Slack notification with simple variables for Workflow Automation
# Send Slack notification
curl -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d @- <<EOF
{
"report_title": "📊 Monthly Demand & Capacity Report - EliD - Prod",
"report_title": "📊 Monthly Demand & Capacity Report - EliD - All Envs",
"report_period": "Last 8 weeks",
"generated_date": "$(date +'%Y-%m-%d %H:%M UTC')",
"widgets_count": "7",
"github_url": "$GITHUB_URL",
"report_name": "$REPORT_NAME"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -639,13 +639,23 @@ resource "aws_iam_policy" "firehose_readonly" {
}

resource "aws_iam_policy" "cloudwatch_management" {
#checkov:skip=CKV_AWS_355: GetMetricWidgetImage requires wildcard resource
#checkov:skip=CKV_AWS_290: GetMetricWidgetImage requires wildcard resource
name = "cloudwatch-management"
description = "Allow GitHub Actions to manage CloudWatch logs, alarms, and SNS topics"
path = "/service-policies/"

policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = [
# GetMetricWidgetImage does not support resource-level permissions
"cloudwatch:GetMetricWidgetImage"
],
Resource = "*"
},
{
Effect = "Allow",
Action = [
Expand All @@ -663,6 +673,7 @@ resource "aws_iam_policy" "cloudwatch_management" {
"cloudwatch:ListTagsForResource",
"cloudwatch:TagResource",
"cloudwatch:UntagResource",
"cloudwatch:GetDashboard",

"sns:CreateTopic",
"sns:DeleteTopic",
Expand All @@ -683,6 +694,7 @@ resource "aws_iam_policy" "cloudwatch_management" {
"arn:aws:logs:${var.default_aws_region}:${data.aws_caller_identity.current.account_id}:log-group:aws-wafv2-logs-*",
"arn:aws:logs:${var.default_aws_region}:${data.aws_caller_identity.current.account_id}:log-group:aws-waf-logs-*",
"arn:aws:cloudwatch:${var.default_aws_region}:${data.aws_caller_identity.current.account_id}:alarm:*",
"arn:aws:cloudwatch::${data.aws_caller_identity.current.account_id}:dashboard/Demand_And_Capacity_*",
"arn:aws:sns:${var.default_aws_region}:${data.aws_caller_identity.current.account_id}:cloudwatch-security-alarms*",
"arn:aws:logs:${var.default_aws_region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/default-eligibility-signposting-api*",
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ data "aws_iam_policy_document" "permissions_boundary" {
"cloudwatch:ListTagsForResource",
"cloudwatch:TagResource",
"cloudwatch:UntagResource",
"cloudwatch:GetDashboard",
"cloudwatch:GetMetricWidgetImage",

# DynamoDB - table management
"dynamodb:DescribeTimeToLive",
Expand Down
15 changes: 6 additions & 9 deletions scripts/export_dashboard_image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
set -e

DASHBOARD_NAME="${1:-Demand_And_Capacity_Prod}"
OUTPUT_DIR="dashboard_exports"
ENVIRONMENT="${2:-Prod}"
OUTPUT_BASE="dashboard_exports"
OUTPUT_DIR="${OUTPUT_BASE}/${ENVIRONMENT}"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
REGION="${AWS_REGION:-eu-west-2}"

Expand All @@ -15,6 +17,7 @@ echo "========================================="
echo "CloudWatch Dashboard Image Export"
echo "========================================="
echo "Dashboard: $DASHBOARD_NAME"
echo "Environment: $ENVIRONMENT"
echo "Region: $REGION"
echo "Output: $OUTPUT_DIR"
echo ""
Expand Down Expand Up @@ -49,7 +52,7 @@ import sys
import os

# Read dashboard definition
with open(f"dashboard_exports/dashboard_definition_{os.environ['TIMESTAMP']}.json") as f:
with open(f"{os.environ['OUTPUT_DIR']}/dashboard_definition_{os.environ['TIMESTAMP']}.json") as f:
dashboard_data = json.load(f)

# Parse the dashboard body
Expand Down Expand Up @@ -133,10 +136,4 @@ print("========================================")
PYTHON_SCRIPT

echo ""
echo "Generating HTML report..."
python3 scripts/generate_dashboard_report.py --input "${OUTPUT_DIR}"

echo ""
echo "✓ Complete! Check the ${OUTPUT_DIR}/ directory for:"
echo " - Individual widget images (PNG files)"
echo " - Combined HTML report (dashboard_report_*.html)"
echo "✓ Export for $ENVIRONMENT complete!"
Loading
Loading