Skip to content

Ubuntu 24.04 Base Image OS Refresh (CVE Monitor) #18

Ubuntu 24.04 Base Image OS Refresh (CVE Monitor)

Ubuntu 24.04 Base Image OS Refresh (CVE Monitor) #18

name: Ubuntu 24.04 Base Image OS Refresh (CVE Monitor)
# This workflow monitors Ubuntu 24.04 security notices and automatically triggers
# staging and production rebuilds when new security fixes are detected.
#
# Flow:
# 1. Check Ubuntu Security JSON API for Ubuntu 24.04 (Noble) security notices
# 2. If new notices found in lookback period (default: 48 hours), trigger staging build for each version (with SkipGit=true)
# 3. Wait for staging to complete successfully (up to 2 hours)
# 4. If staging succeeds, trigger production release
#
# Requirements:
# - GITHUB_TOKEN must have workflow dispatch permissions
# - Versions are automatically extracted from git tags (latest N major.minor releases)
# - Uses JSON API: https://ubuntu.com/security/notices.json
#
# Configuration (for manual runs):
# - versions_to_refresh: Number of recent major.minor versions (default: 2)
# - hours_lookback: How many hours to look back for notices (default: 48)
#
# Repository Variables (optional, set in Settings > Secrets and variables > Actions > Variables):
# - CVE_MONITOR_HOURS_LOOKBACK: Override the default lookback period (e.g., '48', '72', '24')
# - CVE_MONITOR_VERSIONS_COUNT: Override the default number of recent versions to refresh (e.g., '2', '3', '1')
on:
schedule:
# Run every 48 hours (every 2 days)
- cron: '0 0 */2 * *'
workflow_dispatch:
inputs:
versions_to_refresh:
description: 'Number of recent major.minor versions to refresh (e.g., 2 means latest and n-1)'
default: '2'
type: string
required: false
hours_lookback:
description: 'Number of hours to look back for security notices (default: 48)'
default: '48'
type: string
required: false
permissions:
actions: write # Required to trigger other workflows
contents: read # Required to read repository content
jobs:
check-cves:
name: Check for Ubuntu 24.04 CVEs
runs-on: ubuntu-latest
outputs:
has-cves: ${{ steps.filter-cves.outputs.has_cves }}
versions: ${{ steps.extract-versions.outputs.versions }}
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history to get all tags
- name: Fetch Ubuntu Security Notices JSON
id: fetch-json
run: |
echo "Fetching Ubuntu Security Notices JSON..."
curl -s https://ubuntu.com/security/notices.json > notices.json
if [ ! -s notices.json ]; then
echo "Error: Failed to fetch security notices JSON"
exit 1
fi
# Validate JSON
if ! jq empty notices.json 2>/dev/null; then
echo "Error: Invalid JSON response"
exit 1
fi
TOTAL_NOTICES=$(jq '.notices | length' notices.json)
echo "✓ Fetched $TOTAL_NOTICES security notices successfully"
- name: Filter for Ubuntu 24.04 Security Notices
id: filter-cves
run: |
# ============================================================================
# JSON API Parsing Logic
# ============================================================================
#
# The Ubuntu Security JSON API (https://ubuntu.com/security/notices.json)
# provides structured security notices with the following relevant fields:
#
# {
# "id": "USN-XXXX-X",
# "published": "2026-01-09T19:45:59.741393",
# "releases": [
# {
# "codename": "noble",
# "version": "24.04",
# "support_tag": "LTS"
# }
# ]
# }
#
# Filtering approach:
# 1. Check if notice was published in the last 12 hours
# 2. Check if releases array contains codename "noble" (Ubuntu 24.04)
# 3. No severity filtering (refresh for any security fix)
# ============================================================================
# Configuration
AFFECTED_RELEASE="noble" # Ubuntu 24.04 codename
# Use input parameter if provided, otherwise use repository variable, otherwise default to 48
HOURS_LOOKBACK="${{ github.event.inputs.hours_lookback || vars.CVE_MONITOR_HOURS_LOOKBACK || '48' }}"
# Calculate cutoff timestamp in ISO format
CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S")
CUTOFF_TIMESTAMP=$(date -u -d "$HOURS_LOOKBACK hours ago" +"%Y-%m-%dT%H:%M:%S")
echo "Current time (UTC): $CURRENT_TIME"
echo "Looking back: $HOURS_LOOKBACK hours"
echo "Cutoff timestamp: $CUTOFF_TIMESTAMP"
echo "Filtering for release: $AFFECTED_RELEASE (Ubuntu 24.04 LTS)"
echo ""
# First, show total Ubuntu 24.04 notices for context
TOTAL_NOBLE_NOTICES=$(jq --arg release "$AFFECTED_RELEASE" '[.notices[] | select(.releases[]? | .codename == $release)] | length' notices.json)
echo "Total Ubuntu 24.04 notices in feed: $TOTAL_NOBLE_NOTICES"
# Show most recent 3 Ubuntu 24.04 notices for debugging
echo ""
echo "Most recent Ubuntu 24.04 notices (for reference):"
jq -r --arg release "$AFFECTED_RELEASE" '.notices[] | select(.releases[]? | .codename == $release) | "\(.id): \(.published)"' notices.json | head -3
echo ""
# Filter notices using jq:
# 1. Filter by published date (matches cutoff)
# 2. Filter by releases containing noble
RECENT_NOTICES=$(jq -r --arg cutoff "$CUTOFF_TIMESTAMP" --arg release "$AFFECTED_RELEASE" '
.notices[] |
select(.published >= $cutoff) |
select(.releases[]? | .codename == $release) |
.id
' notices.json)
if [ -n "$RECENT_NOTICES" ]; then
# Count notices
NOTICE_COUNT=$(echo "$RECENT_NOTICES" | wc -l)
echo "✓ Found $NOTICE_COUNT security notice(s) affecting Ubuntu 24.04 in the last $HOURS_LOOKBACK hours"
echo "has_cves=true" >> $GITHUB_OUTPUT
# Log details with full notice information
echo ""
echo "Security Notices:"
echo "$RECENT_NOTICES" | while read -r usn_id; do
if [ -n "$usn_id" ]; then
TITLE=$(jq -r --arg id "$usn_id" '.notices[] | select(.id == $id) | .title' notices.json)
PUBLISHED=$(jq -r --arg id "$usn_id" '.notices[] | select(.id == $id) | .published' notices.json)
echo " - $usn_id: $TITLE"
echo " Published: $PUBLISHED"
echo " Link: https://ubuntu.com/security/notices/$usn_id"
fi
done
else
echo "✗ No security notices found for Ubuntu 24.04 in the past $HOURS_LOOKBACK hours"
echo "has_cves=false" >> $GITHUB_OUTPUT
fi
- name: Extract Versions to Refresh
id: extract-versions
run: |
# Check if we need to extract versions
if [ "${{ steps.filter-cves.outputs.has_cves }}" = "false" ]; then
echo "No CVEs detected, skipping version extraction"
echo 'versions=[]' >> $GITHUB_OUTPUT
exit 0
fi
# ============================================================================
# Dynamic Version Extraction from Git Tags
# ============================================================================
#
# Version format:
# - Regular: x.x.x (e.g., 25.12.1)
# - Hotfix: x.x.x.x (e.g., 25.12.1.1)
#
# Logic:
# 1. Get all tags matching version pattern
# 2. Group by major.minor (e.g., 25.12.x)
# 3. For each group, get the latest version (including hotfixes)
# 4. Select the latest N releases (configurable)
#
# Example with VERSIONS_TO_REFRESH=2:
# Tags: 25.10.1, 25.11.1, 25.11.1.1, 25.11.1.2, 25.12.1
# Result: ["25.12.1", "25.11.1.2"] (latest of 25.12 and 25.11)
# ============================================================================
# Configuration: Number of recent major.minor versions to refresh
# Use input parameter if provided, otherwise use repository variable, otherwise default to 2
VERSIONS_TO_REFRESH="${{ github.event.inputs.versions_to_refresh || vars.CVE_MONITOR_VERSIONS_COUNT || '2' }}"
echo "Extracting versions to refresh..."
echo "Configuration: Will refresh last $VERSIONS_TO_REFRESH major.minor releases"
echo ""
# Get all tags matching version pattern (x.x.x or x.x.x.x)
ALL_TAGS=$(git tag | grep -E '^[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?$' | sort -V)
if [ -z "$ALL_TAGS" ]; then
echo "⚠️ No version tags found in repository"
echo 'versions=[]' >> $GITHUB_OUTPUT
exit 0
fi
echo "Found version tags:"
echo "$ALL_TAGS" | tail -10
echo ""
# Extract unique major.minor versions and get the latest patch/hotfix for each
# Group by major.minor (e.g., 25.12), then pick the highest version in that group
LATEST_PER_MINOR=$(echo "$ALL_TAGS" | awk -F. '{
key = $1 "." $2
if (key in versions) {
if ($0 > versions[key]) {
versions[key] = $0
}
} else {
versions[key] = $0
}
}
END {
for (key in versions) {
print versions[key]
}
}' | sort -V)
echo "Latest version per major.minor:"
echo "$LATEST_PER_MINOR"
echo ""
# Get the last N versions
VERSIONS_TO_BUILD=$(echo "$LATEST_PER_MINOR" | tail -n $VERSIONS_TO_REFRESH)
echo "Selected versions to refresh (last $VERSIONS_TO_REFRESH):"
echo "$VERSIONS_TO_BUILD"
echo ""
# Convert to JSON array format
VERSIONS_JSON=$(echo "$VERSIONS_TO_BUILD" | jq -R -s -c 'split("\n") | map(select(length > 0))')
echo "versions=$VERSIONS_JSON" >> $GITHUB_OUTPUT
echo "✓ Will refresh versions: $VERSIONS_JSON"
- name: Summary
run: |
echo "### Security Notice Check Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Release:** Ubuntu 24.04 (Noble)" >> $GITHUB_STEP_SUMMARY
echo "- **Lookback:** ${{ github.event.inputs.hours_lookback || vars.CVE_MONITOR_HOURS_LOOKBACK || '48' }} hours" >> $GITHUB_STEP_SUMMARY
echo "- **Security Notices Found:** ${{ steps.filter-cves.outputs.has_cves }}" >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.filter-cves.outputs.has_cves }}" = "true" ]; then
echo "- **Action:** Triggering refresh workflows" >> $GITHUB_STEP_SUMMARY
echo "- **Versions to Refresh:** ${{ steps.extract-versions.outputs.versions }}" >> $GITHUB_STEP_SUMMARY
echo "- **Refresh Policy:** Last ${{ github.event.inputs.versions_to_refresh || vars.CVE_MONITOR_VERSIONS_COUNT || '2' }} major.minor releases" >> $GITHUB_STEP_SUMMARY
else
echo "- **Action:** No refresh needed" >> $GITHUB_STEP_SUMMARY
fi
refresh-versions:
name: Refresh Version ${{ matrix.version }}
runs-on: ubuntu-latest
needs: check-cves
if: needs.check-cves.outputs.has-cves == 'true'
strategy:
matrix:
version: ${{ fromJson(needs.check-cves.outputs.versions) }}
fail-fast: false # Continue other versions even if one fails
steps:
- name: Notify Slack - Staging Build Triggered (Security Fix)
env:
SLACK_WEBHOOK_URL: ${{ secrets.STG_SLACK_WEBHOOK_URL }}
run: |
echo "📤 Sending Slack notification to staging channel..."
STATUS_EMOJI="🔐"
COLOR="warning"
VERSION="${{ matrix.version }}"
WORKFLOW_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
# Create staging notification for Ubuntu security fix trigger
SLACK_MESSAGE=$(cat <<EOF
🔐 *Staging Build Triggered - Ubuntu Security Fix*
📦 *Version:* \`$VERSION\`
🔄 *Trigger:* Automated Ubuntu 24.04 Security Fix (Scheduled)
⚙️ Staging base images build has been triggered to address Ubuntu 24.04 security notices.
This is an *automated security refresh*, not a manual release.
🔗 Workflow: <${WORKFLOW_URL}|View Run>
⏳ Build in progress...
EOF
)
echo "Message preview:"
echo "$SLACK_MESSAGE"
# Send to Slack using webhook
if [ -n "$SLACK_WEBHOOK_URL" ]; then
payload=$(jq -n \
--arg text "$SLACK_MESSAGE" \
--arg color "$COLOR" \
--arg version "$VERSION" \
'{"text": $text, "attachments": [{"color": $color, "fields": [{"title": "Version", "value": $version, "short": true}]}]}')
HTTP_STATUS=$(curl -s -w "%{http_code}" -o /dev/null -X POST \
-H 'Content-type: application/json' \
--data "$payload" \
"$SLACK_WEBHOOK_URL")
if [ "$HTTP_STATUS" -eq 200 ]; then
echo "✅ Slack notification sent successfully to staging channel"
else
echo "❌ Failed to send Slack notification (HTTP $HTTP_STATUS)"
fi
else
echo "⚠️ STG_SLACK_WEBHOOK_URL not set, skipping notification"
fi
- name: Trigger Staging Build for version ${{ matrix.version }}
id: trigger-staging
run: |
echo "Triggering Staging Build (base image refresh) for version ${{ matrix.version }}..."
WORKFLOW_FILE="stg-from-version-build-push-tag-base-image.yaml"
curl -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/${{ github.repository }}/actions/workflows/${WORKFLOW_FILE}/dispatches \
-d "{\"ref\":\"main\",\"inputs\":{\"Tag\":\"${{ matrix.version }}\",\"IsLatest\":\"true\",\"SkipGit\":\"true\",\"CopyVersionScript\":\"true\"}}"
if [ $? -eq 0 ]; then
echo "✓ Successfully triggered Staging Build"
echo "staging_triggered=true" >> $GITHUB_OUTPUT
else
echo "✗ Failed to trigger Staging Build"
echo "staging_triggered=false" >> $GITHUB_OUTPUT
exit 1
fi
- name: Wait for Staging Build to start
run: |
echo "Waiting for Staging Build to start..."
# Give GitHub Actions time to queue and start the workflow
sleep 30
- name: Early Failure Check
id: early-check
run: |
echo "Performing early failure check (after 3 minutes)..."
echo "This catches fast failures before entering the long polling loop"
# Wait 3 minutes for the job to start and potentially fail fast
sleep 180
WORKFLOW_FILE="stg-from-version-build-push-tag-base-image.yaml"
# Get the latest workflow run on main branch
RESPONSE=$(curl -s \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/${{ github.repository }}/actions/workflows/${WORKFLOW_FILE}/runs?per_page=1&branch=main")
STATUS=$(echo "$RESPONSE" | jq -r '.workflow_runs[0].status')
CONCLUSION=$(echo "$RESPONSE" | jq -r '.workflow_runs[0].conclusion')
echo "Early check - Status: $STATUS, Conclusion: $CONCLUSION"
# If already failed, exit early
if [ "$STATUS" = "completed" ] && [ "$CONCLUSION" != "success" ]; then
echo "❌ Staging Build failed early (within 3 minutes)"
echo "early_failure=true" >> $GITHUB_OUTPUT
exit 1
fi
echo "✓ No early failure detected, proceeding to normal monitoring"
echo "early_failure=false" >> $GITHUB_OUTPUT
- name: Wait for Build Progress
if: steps.early-check.outputs.early_failure == 'false'
run: |
echo "Early check passed - staging build is running normally"
echo "Waiting 12 more minutes before starting status checks..."
echo "Rationale: Staging builds take minimum 15 minutes, and we just checked at 3 minutes"
# Wait 12 minutes (720 seconds)
sleep 720
echo "✓ Initial build period complete, now starting regular status checks"
- name: Check Staging Build status
id: check-staging
if: steps.early-check.outputs.early_failure == 'false'
run: |
echo "Monitoring Staging Build completion status..."
WORKFLOW_FILE="stg-from-version-build-push-tag-base-image.yaml"
MAX_WAIT_MINUTES=120 # Wait up to 2 hours for staging build
CHECK_INTERVAL=120 # Check every 2 minutes
echo "Already waited 15 minutes (3min early check + 12min build time)"
echo "Will check status every ${CHECK_INTERVAL}s for up to ${MAX_WAIT_MINUTES} minutes"
for i in $(seq 1 $MAX_WAIT_MINUTES); do
echo "Check attempt $i/$MAX_WAIT_MINUTES..."
# Get the latest workflow run on main branch
RESPONSE=$(curl -s \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/${{ github.repository }}/actions/workflows/${WORKFLOW_FILE}/runs?per_page=1&branch=main")
STATUS=$(echo "$RESPONSE" | jq -r '.workflow_runs[0].status')
CONCLUSION=$(echo "$RESPONSE" | jq -r '.workflow_runs[0].conclusion')
RUN_ID=$(echo "$RESPONSE" | jq -r '.workflow_runs[0].id')
echo " Run ID: $RUN_ID"
echo " Status: $STATUS"
echo " Conclusion: $CONCLUSION"
if [ "$STATUS" = "completed" ]; then
if [ "$CONCLUSION" = "success" ]; then
echo "✓ Staging Build completed successfully"
echo "staging_success=true" >> $GITHUB_OUTPUT
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT
exit 0
else
echo "✗ Staging Build failed with conclusion: $CONCLUSION"
echo "staging_success=false" >> $GITHUB_OUTPUT
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT
exit 0
fi
fi
echo " Staging Build still running, waiting ${CHECK_INTERVAL}s..."
sleep $CHECK_INTERVAL
done
echo "⚠️ Staging Build did not complete within ${MAX_WAIT_MINUTES} minutes"
echo "staging_success=false" >> $GITHUB_OUTPUT
- name: Trigger Production Release for version ${{ matrix.version }}
if: steps.check-staging.outputs.staging_success == 'true' && steps.early-check.outputs.early_failure != 'true'
id: trigger-production
run: |
echo "Staging Build succeeded. Triggering Production Release for version ${{ matrix.version }}..."
WORKFLOW_FILE="prod-from-version-build-push-tag-base-image.yaml"
curl -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/${{ github.repository }}/actions/workflows/${WORKFLOW_FILE}/dispatches \
-d "{\"ref\":\"main\",\"inputs\":{\"Version\":\"${{ matrix.version }}\",\"IsLatest\":\"true\"}}"
if [ $? -eq 0 ]; then
echo "✓ Successfully triggered Production Release"
echo "production_triggered=true" >> $GITHUB_OUTPUT
else
echo "✗ Failed to trigger Production Release"
echo "production_triggered=false" >> $GITHUB_OUTPUT
exit 1
fi
- name: Skip Production Release (Staging Build failed)
if: steps.check-staging.outputs.staging_success != 'true'
run: |
echo "⚠️ Skipping Production Release because Staging Build did not complete successfully"
echo "Version ${{ matrix.version }} will not be fully refreshed"
- name: Version Summary
if: always()
run: |
echo "### Version ${{ matrix.version }} Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Staging Build Triggered:** ${{ steps.trigger-staging.outputs.staging_triggered }}" >> $GITHUB_STEP_SUMMARY
echo "- **Staging Build Success:** ${{ steps.check-staging.outputs.staging_success }}" >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.check-staging.outputs.staging_success }}" = "true" ]; then
echo "- **Production Release Triggered:** ${{ steps.trigger-production.outputs.production_triggered }}" >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.check-staging.outputs.run_id }}" != "" ]; then
echo "- **Staging Run ID:** ${{ steps.check-staging.outputs.run_id }}" >> $GITHUB_STEP_SUMMARY
fi
echo "- **Status:** ✅ Refresh Complete" >> $GITHUB_STEP_SUMMARY
else
echo "- **Production Release Triggered:** ✗ No (Staging Build failed)" >> $GITHUB_STEP_SUMMARY
echo "- **Status:** ❌ Refresh Incomplete" >> $GITHUB_STEP_SUMMARY
fi
summary:
name: Workflow Summary
runs-on: ubuntu-latest
needs: [check-cves, refresh-versions]
if: always()
steps:
- name: Checkout code for scripts
if: needs.check-cves.outputs.has-cves == 'true'
uses: actions/checkout@v3
- name: Generate Summary
run: |
echo "# Ubuntu 24.04 CVE Monitor - Execution Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Timestamp:** $(date -u)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.check-cves.outputs.has-cves }}" = "true" ]; then
echo "## ✅ Security Notices Detected" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "New security notices affecting Ubuntu 24.04 were found." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Versions Processed:** ${{ needs.check-cves.outputs.versions }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Refresh Status:** Check individual version summaries above" >> $GITHUB_STEP_SUMMARY
else
echo "## ✓ No Security Notices Detected" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "No security notices found for Ubuntu 24.04 in the past ${{ github.event.inputs.hours_lookback || vars.CVE_MONITOR_HOURS_LOOKBACK || '48' }} hours." >> $GITHUB_STEP_SUMMARY
echo "No refresh actions were needed." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "*Next check in 48 hours*" >> $GITHUB_STEP_SUMMARY
- name: Notify Slack - CVE Refresh Complete
if: needs.check-cves.outputs.has-cves == 'true'
env:
SLACK_WEBHOOK_URL: ${{ secrets.PRD_SLACK_WEBHOOK_URL }}
run: |
echo "📤 Sending Slack notification for CVE refresh..."
# Parse versions from JSON array
VERSIONS='${{ needs.check-cves.outputs.versions }}'
VERSION_LIST=$(echo "$VERSIONS" | jq -r '.[]' | sed 's/^/• `/' | sed 's/$/`/' | tr '\n' ' ' | sed 's/ $/\n/')
# Determine overall status
if [ "${{ needs.refresh-versions.result }}" = "success" ]; then
STATUS_EMOJI="🔄"
STATUS_MESSAGE="Security Refresh Complete"
COLOR="good"
DETAIL_MESSAGE="All base images have been successfully rebuilt and deployed to address Ubuntu 24.04 security notices."
else
STATUS_EMOJI="⚠️"
STATUS_MESSAGE="Security Refresh Completed with Issues"
COLOR="warning"
DETAIL_MESSAGE="Security refresh completed but some versions may have encountered issues. Check the workflow logs for details."
fi
# Store GitHub Actions variables as bash variables
WORKFLOW_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
HOURS_CONFIG="${{ github.event.inputs.hours_lookback || vars.CVE_MONITOR_HOURS_LOOKBACK || '48' }}"
# Create Slack message line by line
SLACK_MESSAGE=$(printf "%s\n\n%s\n%s\n\n%s\n%s\n\n%s\n\n%s" \
"$STATUS_EMOJI *Ubuntu 24.04 $STATUS_MESSAGE*" \
"📋 *Versions Refreshed:*" \
"$VERSION_LIST" \
"🔐 *Reason:* New security notices detected for Ubuntu 24.04 (Noble)" \
"$STATUS_EMOJI $DETAIL_MESSAGE" \
"🔗 Workflow: <${WORKFLOW_URL}|View Run>" \
"⏰ Next automatic check in ${HOURS_CONFIG} hours")
echo "Message preview:"
echo "$SLACK_MESSAGE"
# Send to Slack using webhook
if [ -n "$SLACK_WEBHOOK_URL" ]; then
# Build JSON payload
payload=$(jq -n \
--arg text "$SLACK_MESSAGE" \
--arg color "$COLOR" \
--arg status "$STATUS_MESSAGE" \
'{"text": $text, "attachments": [{"color": $color, "fields": [{"title": "Status", "value": $status, "short": false}]}]}')
# Send to Slack (silent mode to avoid logging webhook URL)
HTTP_STATUS=$(curl -s -w "%{http_code}" -o /dev/null -X POST \
-H 'Content-type: application/json' \
--data "$payload" \
"$SLACK_WEBHOOK_URL")
if [ "$HTTP_STATUS" -eq 200 ]; then
echo "✅ Slack notification sent successfully"
else
echo "❌ Failed to send Slack notification (HTTP $HTTP_STATUS)"
fi
else
echo "⚠️ SLACK_WEBHOOK_URL not set, skipping notification"
fi