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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codespellrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Lint Codespell configurations
[codespell]
skip = .codespellrc,.git,node_modules,build,dist,*.zst,CHANGELOG.md,.playwright,.terraform,*.svg,**/pepr/operator/crd/generated/*.ts,**/uds-docs/**
skip = .codespellrc,.git,node_modules,build,dist,*.zst,CHANGELOG.md,.playwright,.terraform,*.svg,**/pepr/operator/crd/generated/*.ts,**/uds-docs/**,**/package-lock.json
ignore-words-list = NotIn,AKS,LICENS,aks,afterAll
enable-colors =
check-hidden =
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"jest.*.js",
"test/playwright/",
"test/jest/",
"scripts/",
"uds-docs/"
],
"root": true,
Expand Down
82 changes: 82 additions & 0 deletions .github/actions/renovate-readiness/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Renovate Readiness Action

This GitHub Action automates the process of checking if Renovate PRs are ready for testing.

## Overview

UDS Core uses [Renovate](https://github.com/renovatebot/renovate) to track and automate dependency updates. Due to support for 3 flavors of core (upstream, registry1, and unicorn), most dependency updates are not ready when the PRs are first opened. This action automates the process of checking if a PR is ready for testing.

## How It Works

The action performs the following steps:

1. **Manual Override Check**: If the PR has the `renovate-ready` label, the action will set `should_process` to `false` and skip all other checks, allowing CI to proceed.

2. **Branch Name Processing**: The action extracts the package name from the branch name by removing the `renovate/` prefix.

3. **Special Case Handling**:
- **Pepr Updates**: For Pepr updates, the action compares the version in `package.json` with the image versions in `tasks/create.yaml`. If they don't match, it adds the `waiting on ironbank` label.
- **Support Dependencies**: For support dependency updates, the action adds the `needs-review` label and sets `should_process` to `false` to prevent excessive IAC runs.

4. **Regular Package Updates**:
- The action performs sparse checkouts of the relevant package directory from both the PR branch and the main branch.
- It extracts images and charts from both branches using the `getImagesAndCharts.ts` script.
- It compares the extracted data using the `compareImagesAndCharts.ts` script.
- Based on the comparison, it applies appropriate labels to the PR:
- `waiting on ironbank`: If a registry1 image is behind
- `waiting on cgr`: If a chainguard image is behind
- `helm-chart-only`: If a PR only contains a helm chart update
- `needs-review`: If PR is NOT waiting on image updates
- `major-helm-update`: If the PR contains a major chart version bump
- `major-image-update`: If the PR contains a major image version bump
- If any `waiting on` labels are applied, the action sets `should_process` to `false` to prevent running CI.

## Usage

The action is automatically triggered for all Renovate PRs in the slim-dev-test.yaml workflow. No manual intervention is required.

### Manual Override

If you want to force a PR to run CI regardless of its readiness status, add the `renovate-ready` label to the PR.

## Implementation Details

- **TypeScript Scripts**: The core logic for extracting and comparing images and charts is implemented in TypeScript scripts located in the `scripts/renovate` directory.
- `getImagesAndCharts.ts`: Extracts images and charts from zarf.yaml files in a directory.
- `compareImagesAndCharts.ts`: Compares extracted images and charts between two directories and determines if the PR is ready for testing.
- **GitHub Action**: The GitHub Action orchestrates the process, handling special cases and applying labels based on the script outputs.
- **Workflow Integration**: The action is integrated into the slim-dev-test.yaml workflow, which is triggered for all PRs.
- **Output Variables**:
- `should_process`: Indicates whether the PR should proceed with CI. Set to `false` if the PR has the `renovate-ready` label or if it's waiting on image updates.
- `needs_comparison`: Indicates whether the PR needs to run the comparison scripts. Set to `false` for special cases like Pepr updates.

## Testing

The TypeScript scripts are thoroughly tested using Jest:

- **getImagesAndCharts.test.ts**: Tests the extraction of images and charts from zarf.yaml files, including edge cases like:
- Empty directories
- Invalid YAML files
- Missing components
- Images without version tags

- **compareImagesAndCharts.test.ts**: Tests the comparison of images and charts, including:
- Helm chart updates (both regular and major)
- Image updates (including major updates)
- Waiting conditions for Ironbank and Chainguard images
- Missing or empty extract files
- Invalid version formats

## Troubleshooting

If you encounter issues with the action, check the following:

1. **PR Labels**: Check if the PR has any `waiting on` labels, which indicate what the PR is waiting for.
2. **Action Logs**: Check the action logs for any errors or warnings.
3. **Manual Override**: If needed, add the `renovate-ready` label to force the PR to run CI.
4. **Debug Output**: The action outputs detailed information about its decisions, which can help diagnose issues.

## Related Documentation

- [Renovate PR Process](https://www.notion.so/Renovate-PR-Process-182e512f24fc80479d35f956a7c42388?pvs=21)
- [Renovate Documentation](https://docs.renovatebot.com/)
197 changes: 193 additions & 4 deletions .github/actions/renovate-readiness/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,203 @@
name: renovate-readiness
description: "Check if Renovate PRs are ready for testing"

inputs:
github_token:
description: "GitHub token for API calls"
required: true

runs:
using: composite
steps:
# This is current a stub for future logic that would auto-detect readiness
# In lieu of that, we require an engineer to review changes and manually add the `renovate-ready` label
# Check if PR has the renovate-ready label (manual override)
- name: Check if PR has the ready label
if: ${{ ! contains(github.event.pull_request.labels.*.name, 'renovate-ready') }}
id: check-ready-label
run: |
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'renovate-ready') }}" == "true" ]]; then
echo "PR has the renovate-ready label. Skipping readiness check."
echo "should_process=false" >> $GITHUB_OUTPUT
else
echo "PR does not have the renovate-ready label. Proceeding with readiness check."
echo "should_process=true" >> $GITHUB_OUTPUT
fi
shell: bash

# Process branch name to determine package
- name: Process branch name
id: process-branch
if: steps.check-ready-label.outputs.should_process == 'true'
env:
BRANCH_NAME: ${{ github.head_ref }}
run: |
echo "Branch name: $BRANCH_NAME"

# Remove 'renovate/' prefix if present
if [[ $BRANCH_NAME == renovate/* ]]; then
PACKAGE_NAME=${BRANCH_NAME#renovate/}
echo "Package name after removing prefix: $PACKAGE_NAME"
else
PACKAGE_NAME=$BRANCH_NAME
echo "Branch doesn't have renovate/ prefix, using as is: $PACKAGE_NAME"
fi

# Handle special cases
if [[ "$PACKAGE_NAME" == "pepr" ]]; then
echo "Detected Pepr update"
echo "package=pepr" >> $GITHUB_OUTPUT
echo "is_pepr=true" >> $GITHUB_OUTPUT
echo "needs_comparison=false" >> $GITHUB_OUTPUT
elif [[ "$PACKAGE_NAME" == "support-deps" ]]; then
echo "Detected support dependencies update"
echo "package=support-deps" >> $GITHUB_OUTPUT
echo "is_support_deps=true" >> $GITHUB_OUTPUT
echo "needs_comparison=false" >> $GITHUB_OUTPUT
else
echo "Regular package update: $PACKAGE_NAME"
echo "package=$PACKAGE_NAME" >> $GITHUB_OUTPUT
echo "needs_comparison=true" >> $GITHUB_OUTPUT
fi
shell: bash

# Handle Pepr updates
- name: Handle Pepr update
if: steps.process-branch.outputs.is_pepr == 'true'
run: |
# Get Pepr version from package.json
PEPR_VERSION=$(jq -r '.dependencies.pepr' package.json)
echo "Pepr version from package.json: $PEPR_VERSION"

# Get image versions from tasks/create.yaml
IRONBANK_IMAGE_VERSION=$(yq e '.variables[] | select(.name == "REGISTRY1_PEPR_IMAGE") | .default | split(":")[1]' tasks/create.yaml)
IRONBANK_IMAGE_VERSION=${IRONBANK_IMAGE_VERSION#v}
echo "Ironbank image version: $IRONBANK_IMAGE_VERSION"

# Compare versions
if [[ "$PEPR_VERSION" != "$IRONBANK_IMAGE_VERSION" ]]; then
echo "Pepr version mismatch. Waiting on Ironbank image update."
gh pr edit ${{ github.event.pull_request.number }} --add-label "waiting on ironbank"
exit 1
else
echo "Pepr versions match. Ready for review."
gh pr edit ${{ github.event.pull_request.number }} --remove-label "waiting on ironbank" || true
gh pr edit ${{ github.event.pull_request.number }} --add-label "needs-review"
fi
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}

# Handle support dependencies
- name: Handle support dependencies
if: steps.process-branch.outputs.is_support_deps == 'true'
run: |
echo "Support dependencies update detected. Needs manual review."
gh pr edit ${{ github.event.pull_request.number }} --add-label "needs-review"
# Fail the job to prevent excessive CI runs of IAC clusters
exit 1
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}

# Checkout PR branch (sparse checkout of src/<pkg>)
- name: Checkout PR branch
if: steps.process-branch.outputs.needs_comparison == 'true'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
ref: ${{ github.event.pull_request.head.ref }}
path: new
sparse-checkout: |
src/${{ steps.process-branch.outputs.package }}
sparse-checkout-cone-mode: false

# Checkout main branch (sparse checkout of src/<pkg>)
- name: Checkout main branch
if: steps.process-branch.outputs.needs_comparison == 'true'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
ref: main
path: old
sparse-checkout: |
src/${{ steps.process-branch.outputs.package }}
sparse-checkout-cone-mode: false

# Install dependencies
- name: Install dependencies
if: steps.process-branch.outputs.needs_comparison == 'true'
run: |
cd scripts/renovate
npm install
shell: bash

# Extract images and charts from old branch
- name: Extract images and charts from old branch
if: steps.process-branch.outputs.needs_comparison == 'true'
run: |
cd scripts/renovate
npx ts-node getImagesAndCharts.ts $GITHUB_WORKSPACE/old
shell: bash

# Extract images and charts from new branch
- name: Extract images and charts from new branch
if: steps.process-branch.outputs.needs_comparison == 'true'
run: |
cd scripts/renovate
npx ts-node getImagesAndCharts.ts $GITHUB_WORKSPACE/new
shell: bash

# Compare images and charts
- name: Compare images and charts
id: compare
if: steps.process-branch.outputs.needs_comparison == 'true'
run: |
cd scripts/renovate
OUTPUT=$(npx ts-node compareImagesAndCharts.ts $GITHUB_WORKSPACE/old/extract $GITHUB_WORKSPACE/new/extract)
echo "$OUTPUT"

# Extract labels from output
LABELS=$(echo "$OUTPUT" | grep "LABELS=" | cut -d'=' -f2)
echo "labels=$LABELS" >> $GITHUB_OUTPUT

# Check if waiting on labels are present, or this is a helm chart update only
if [[ "$LABELS" == *"waiting on ironbank"* ]] || [[ "$LABELS" == *"waiting on cgr"* ]] || [[ "$LABELS" == *"helm-chart-only"* ]]; then
echo "waiting=true" >> $GITHUB_OUTPUT
else
echo "waiting=false" >> $GITHUB_OUTPUT
fi
shell: bash

# Apply labels
- name: Apply labels
if: steps.process-branch.outputs.needs_comparison == 'true'
run: |
LABELS="${{ steps.compare.outputs.labels }}"
if [[ -n "$LABELS" ]]; then
echo "New labels to apply: $LABELS"

# Get current labels on the PR
CURRENT_LABELS=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name' | tr '\n' ' ')
echo "Current labels: $CURRENT_LABELS"

# Define the managed labels we care about
MANAGED_LABELS=("waiting on ironbank" "waiting on cgr" "needs-review" "helm-chart-only" "major-helm-update" "major-image-update")

# Remove labels that are currently on the PR but not in the new set
for LABEL in "${MANAGED_LABELS[@]}"; do
if [[ "$CURRENT_LABELS" == *"$LABEL"* ]] && [[ "$LABELS" != *"$LABEL"* ]]; then
echo "Removing outdated label: $LABEL"
gh pr edit ${{ github.event.pull_request.number }} --remove-label "$LABEL" || true
fi
done

# Add the new labels
gh pr edit ${{ github.event.pull_request.number }} --add-label "$LABELS"
fi
shell: bash
env:
GH_TOKEN: ${{ inputs.github_token }}

# Fail if waiting on images
- name: Fail if waiting on images or helm update only
if: steps.compare.outputs.waiting == 'true'
run: |
echo "This PR is not ready to run CI. Failing job."
echo "PR is waiting on image updates or only contains a helm chart update. Failing job."
exit 1
shell: bash
7 changes: 5 additions & 2 deletions .github/workflows/checkpoint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ permissions:
on:
pull_request:
# milestoned is added here as a workaround for release-please not triggering PR workflows (PRs should be added to a milestone to trigger the workflow).
# labeled is added here to allow for "manual" triggering of CI on renovate PRs
types: [milestoned, opened, reopened, synchronize, labeled]
# labeled trigger is safe because GitHub token operations don't trigger new workflow runs
types: [milestoned, labeled, opened, reopened, synchronize]
paths:
- packages/checkpoint-dev/**
- .github/workflows/checkpoint**
Expand All @@ -38,13 +38,16 @@ jobs:
contents: read
packages: write
id-token: write # This is needed for OIDC federation.
pull-requests: write # Allows writing to pull requests (needed for renovate-readiness)

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Check renovate readiness
if: startsWith(github.event.pull_request.head.ref, 'renovate/') # Only call for Renovate PRs
uses: ./.github/actions/renovate-readiness
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

- name: Environment setup
uses: ./.github/actions/setup
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/docs-shim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ permissions:
on:
pull_request:
# milestoned is added here as a workaround for release-please not triggering PR workflows (PRs should be added to a milestone to trigger the workflow).
# labeled is added here to allow for "manual" triggering of CI on renovate PRs
types: [milestoned, opened, reopened, synchronize, labeled]
# labeled trigger is safe because GitHub token operations don't trigger new workflow runs
types: [milestoned, labeled, opened, reopened, synchronize]
paths:
- "**.md"
- "**.jpg"
Expand All @@ -31,13 +31,19 @@ on:
jobs:
lint-check:
runs-on: ubuntu-latest
# Job-level permissions override workflow-level permissions
permissions:
contents: read # Allows reading the content of the repository.
pull-requests: write # Allows writing to pull requests (needed for renovate-readiness)
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Check renovate readiness
if: startsWith(github.event.pull_request.head.ref, 'renovate/') # Only call for Renovate PRs
uses: ./.github/actions/renovate-readiness
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

- name: lint-check
uses: ./.github/actions/lint-check
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/pull-request-conditionals.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ name: Filter
on:
pull_request:
# milestoned is added here as a workaround for release-please not triggering PR workflows (PRs should be added to a milestone to trigger the workflow).
# labeled is added here to allow for "manual" triggering of CI on renovate PRs
types: [milestoned, opened, reopened, synchronize, labeled]
# labeled trigger is safe because GitHub token operations don't trigger new workflow runs
types: [milestoned, labeled, opened, reopened, synchronize]
paths-ignore:
- "**.md"
- "**.jpg"
Expand Down Expand Up @@ -66,6 +66,8 @@ jobs:
- name: Check renovate readiness
if: startsWith(github.event.pull_request.head.ref, 'renovate/') # Only call for Renovate PRs
uses: ./.github/actions/renovate-readiness
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

# Uses a custom action to filter paths for source packages.
- name: Check src paths
Expand Down
Loading
Loading