Merge branch 'feature/beta-release' into renovate/feature/beta-release-pin-dependencies

This commit is contained in:
Jeremy
2026-01-25 09:40:20 -05:00
committed by GitHub
5 changed files with 285 additions and 11 deletions

View File

@@ -84,6 +84,16 @@ jobs:
echo "is_push=false" >> "$GITHUB_OUTPUT"
fi
- name: Sanitize branch name
id: sanitize
run: |
# Sanitize branch name for use in Docker tags and artifact names
# Replace / with - to avoid invalid reference format errors
BRANCH="${{ github.event.workflow_run.head_branch || github.head_ref || github.ref_name }}"
SANITIZED=$(echo "$BRANCH" | tr '/' '-')
echo "branch=${SANITIZED}" >> "$GITHUB_OUTPUT"
echo "📋 Sanitized branch name: ${BRANCH} -> ${SANITIZED}"
- name: Check for PR image artifact
id: check-artifact
if: steps.pr-info.outputs.pr_number != '' || steps.pr-info.outputs.is_push == 'true'
@@ -170,7 +180,8 @@ jobs:
# Normalize image name (GitHub lowercases repository owner names in GHCR)
IMAGE_NAME=$(echo "${{ github.repository_owner }}/charon" | tr '[:upper:]' '[:lower:]')
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ github.event.workflow_run.head_branch }}"
# Use sanitized branch name for Docker tag (/ is invalid in tags)
IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ steps.sanitize.outputs.branch }}"
else
IMAGE_REF="ghcr.io/${IMAGE_NAME}:pr-${{ steps.pr-info.outputs.pr_number }}"
fi
@@ -237,7 +248,7 @@ jobs:
# actions/upload-artifact v4.4.3
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
with:
name: ${{ steps.pr-info.outputs.is_push == 'true' && format('playwright-report-{0}', github.event.workflow_run.head_branch) || format('playwright-report-pr-{0}', steps.pr-info.outputs.pr_number) }}
name: ${{ steps.pr-info.outputs.is_push == 'true' && format('playwright-report-{0}', steps.sanitize.outputs.branch) || format('playwright-report-pr-{0}', steps.pr-info.outputs.pr_number) }}
path: playwright-report/
retention-days: 14

View File

@@ -105,6 +105,16 @@ jobs:
echo "is_push=false" >> "$GITHUB_OUTPUT"
fi
- name: Sanitize branch name
id: sanitize
run: |
# Sanitize branch name for use in artifact names
# Replace / with - to avoid invalid reference format errors
BRANCH="${{ github.event.workflow_run.head_branch || github.head_ref || github.ref_name }}"
SANITIZED=$(echo "$BRANCH" | tr '/' '-')
echo "branch=${SANITIZED}" >> "$GITHUB_OUTPUT"
echo "📋 Sanitized branch name: ${BRANCH} -> ${SANITIZED}"
- name: Check for PR image artifact
id: check-artifact
if: steps.pr-number.outputs.pr_number != '' || steps.pr-number.outputs.is_push == 'true'
@@ -297,7 +307,7 @@ jobs:
# actions/upload-artifact v4.6.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
with:
name: ${{ steps.pr-number.outputs.is_push == 'true' && format('supply-chain-{0}', github.event.workflow_run.head_branch) || format('supply-chain-pr-{0}', steps.pr-number.outputs.pr_number) }}
name: ${{ steps.pr-number.outputs.is_push == 'true' && format('supply-chain-{0}', steps.sanitize.outputs.branch) || format('supply-chain-pr-{0}', steps.pr-number.outputs.pr_number) }}
path: |
sbom.cyclonedx.json
grype-results.json

View File

@@ -71,15 +71,14 @@ jobs:
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="${{ github.event.release.tag_name }}"
elif [[ "${{ github.event_name }}" == "workflow_run" ]]; then
BRANCH="${{ github.event.workflow_run.head_branch }}"
# Extract tag from the workflow that triggered us
if [[ "${{ github.event.workflow_run.head_branch }}" == "main" ]]; then
if [[ "${BRANCH}" == "main" ]]; then
TAG="latest"
elif [[ "${{ github.event.workflow_run.head_branch }}" == "development" ]]; then
elif [[ "${BRANCH}" == "development" ]]; then
TAG="dev"
elif [[ "${{ github.event.workflow_run.head_branch }}" == "nightly" ]]; then
elif [[ "${BRANCH}" == "nightly" ]]; then
TAG="nightly"
elif [[ "${{ github.event.workflow_run.head_branch }}" == "feature/beta-release" ]]; then
TAG="beta"
elif [[ "${{ github.event.workflow_run.event }}" == "pull_request" ]]; then
# Extract PR number from workflow_run context with null handling
PR_NUMBER=$(jq -r '.pull_requests[0].number // empty' <<< '${{ toJson(github.event.workflow_run.pull_requests) }}')
@@ -90,7 +89,9 @@ jobs:
TAG="sha-$(echo ${{ github.event.workflow_run.head_sha }} | cut -c1-7)"
fi
else
TAG="sha-$(echo ${{ github.event.workflow_run.head_sha }} | cut -c1-7)"
# For feature branches and other pushes, sanitize branch name for Docker tag
# Replace / with - to avoid invalid reference format errors
TAG=$(echo "${BRANCH}" | tr '/' '-')
fi
else
TAG="latest"

View File

@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- **GitHub Actions workflows failing with 'invalid reference format' for feature branches containing slashes**: Branch names like `feature/beta-release` now properly sanitized (replacing `/` with `-`) in Docker image tags and artifact names across `playwright.yml`, `supply-chain-verify.yml`, and `supply-chain-pr.yml` workflows
- **PermissionsModal State Synchronization**: Fixed React anti-pattern where `useState` was used like `useEffect`, causing potential stale state when editing different users' permissions
### Added

View File

@@ -1,7 +1,258 @@
# WAF Integration Workflow Fix: wget-style curl Syntax Migration
# WAF-2026-002: Docker Tag Sanitization for Branch Names
**Plan ID**: WAF-2026-002
**Status**: ✅ COMPLETED
**Priority**: High
**Created**: 2026-01-25
**Completed**: 2026-01-25
**Scope**: Fix Docker image tag construction to handle branch names containing forward slashes
---
## Problem Summary
GitHub Actions workflows are failing with "invalid reference format" errors when building/pulling Docker images for feature branches. The root cause is that branch names like `feature/beta-release` contain forward slashes (`/`), which are **invalid characters in Docker image tags**.
### Docker Tag Naming Rules
Docker image tags must match the regex: `[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}`
Invalid characters include:
- Forward slash (`/`) - **causes "invalid reference format" error**
- Colon (`:`) - reserved for tag separator
- Spaces and special characters
---
## Files Affected
### 1. `.github/workflows/playwright.yml` (Line 103)
**Location**: [playwright.yml](.github/workflows/playwright.yml#L103)
**Current (broken):**
```yaml
- name: Start Charon container
run: |
...
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ github.event.workflow_run.head_branch }}"
else
```
**Issue**: `github.event.workflow_run.head_branch` can contain `/` (e.g., `feature/beta-release`)
**Fix:**
```yaml
- name: Start Charon container
run: |
...
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
# Sanitize branch name: replace / with -
SANITIZED_BRANCH=$(echo "${{ github.event.workflow_run.head_branch }}" | tr '/' '-')
IMAGE_REF="ghcr.io/${IMAGE_NAME}:${SANITIZED_BRANCH}"
else
```
---
### 2. `.github/workflows/playwright.yml` (Line 161) - Artifact Naming
**Location**: [playwright.yml](.github/workflows/playwright.yml#L161)
**Current:**
```yaml
- name: Upload Playwright report
uses: actions/upload-artifact@...
with:
name: ${{ steps.pr-info.outputs.is_push == 'true' && format('playwright-report-{0}', github.event.workflow_run.head_branch) || format('playwright-report-pr-{0}', steps.pr-info.outputs.pr_number) }}
```
**Issue**: Artifact names also cannot contain `/`
**Fix:**
Add a step to sanitize the branch name first and use an environment variable:
```yaml
- name: Sanitize branch name for artifact
id: sanitize
run: |
SANITIZED=$(echo "${{ github.event.workflow_run.head_branch }}" | tr '/' '-')
echo "branch=${SANITIZED}" >> $GITHUB_OUTPUT
- name: Upload Playwright report
uses: actions/upload-artifact@...
with:
name: ${{ steps.pr-info.outputs.is_push == 'true' && format('playwright-report-{0}', steps.sanitize.outputs.branch) || format('playwright-report-pr-{0}', steps.pr-info.outputs.pr_number) }}
```
---
### 3. `.github/workflows/supply-chain-verify.yml` (Lines 64-90) - Tag Determination
**Location**: [supply-chain-verify.yml](.github/workflows/supply-chain-verify.yml#L64-L90)
**Current (partial):**
```yaml
- name: Determine Image Tag
id: tag
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="${{ github.event.release.tag_name }}"
elif [[ "${{ github.event_name }}" == "workflow_run" ]]; then
if [[ "${{ github.event.workflow_run.head_branch }}" == "main" ]]; then
TAG="latest"
elif [[ "${{ github.event.workflow_run.head_branch }}" == "development" ]]; then
TAG="dev"
elif [[ "${{ github.event.workflow_run.head_branch }}" == "nightly" ]]; then
TAG="nightly"
elif [[ "${{ github.event.workflow_run.head_branch }}" == "feature/beta-release" ]]; then
TAG="beta"
elif [[ "${{ github.event.workflow_run.event }}" == "pull_request" ]]; then
...
else
TAG="sha-$(echo ${{ github.event.workflow_run.head_sha }} | cut -c1-7)"
fi
```
**Issue**: Only `feature/beta-release` is explicitly mapped. Other feature branches fall through to SHA-based tags which works, BUT there's an implicit assumption that docker-build.yml creates tags that match. The docker-build.yml uses `type=ref,event=branch` which DOES sanitize branch names.
**Analysis**: The logic here is complex. The `docker/metadata-action` in docker-build.yml uses:
```yaml
type=ref,event=branch,enable=${{ startsWith(github.ref, 'refs/heads/feature/') }}
```
According to [docker/metadata-action docs](https://github.com/docker/metadata-action#typeref), `type=ref,event=branch` produces a tag like `feature-beta-release` (slashes replaced with dashes).
**Fix**: Align supply-chain-verify.yml with docker-build.yml's tag sanitization:
```yaml
- name: Determine Image Tag
id: tag
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="${{ github.event.release.tag_name }}"
elif [[ "${{ github.event_name }}" == "workflow_run" ]]; then
BRANCH="${{ github.event.workflow_run.head_branch }}"
if [[ "${BRANCH}" == "main" ]]; then
TAG="latest"
elif [[ "${BRANCH}" == "development" ]]; then
TAG="dev"
elif [[ "${BRANCH}" == "nightly" ]]; then
TAG="nightly"
elif [[ "${BRANCH}" == feature/* ]]; then
# Match docker/metadata-action behavior: type=ref,event=branch replaces / with -
TAG=$(echo "${BRANCH}" | tr '/' '-')
elif [[ "${{ github.event.workflow_run.event }}" == "pull_request" ]]; then
...
else
TAG="sha-$(echo ${{ github.event.workflow_run.head_sha }} | cut -c1-7)"
fi
```
---
### 4. `.github/workflows/supply-chain-pr.yml` (Line 196) - Artifact Naming
**Location**: [supply-chain-pr.yml](.github/workflows/supply-chain-pr.yml#L196)
**Current:**
```yaml
- name: Upload supply chain artifacts
uses: actions/upload-artifact@...
with:
name: ${{ steps.pr-number.outputs.is_push == 'true' && format('supply-chain-{0}', github.event.workflow_run.head_branch) || format('supply-chain-pr-{0}', steps.pr-number.outputs.pr_number) }}
```
**Issue**: Same artifact naming issue with unsanitized branch names
**Fix:**
```yaml
- name: Sanitize branch name
id: sanitize
if: steps.pr-number.outputs.is_push == 'true'
run: |
SANITIZED=$(echo "${{ github.event.workflow_run.head_branch }}" | tr '/' '-')
echo "branch=${SANITIZED}" >> $GITHUB_OUTPUT
- name: Upload supply chain artifacts
uses: actions/upload-artifact@...
with:
name: ${{ steps.pr-number.outputs.is_push == 'true' && format('supply-chain-{0}', steps.sanitize.outputs.branch) || format('supply-chain-pr-{0}', steps.pr-number.outputs.pr_number) }}
```
---
## How docker/metadata-action Handles This
The `docker/metadata-action` correctly handles this via `type=ref,event=branch`:
From [docker-build.yml](.github/workflows/docker-build.yml#L89-L95):
```yaml
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
...
type=ref,event=branch,enable=${{ startsWith(github.ref, 'refs/heads/feature/') }}
```
The `type=ref,event=branch` option automatically sanitizes the branch name, replacing `/` with `-`.
**Result**: Feature branch `feature/beta-release` produces tag `feature-beta-release`
---
## Summary Table
| Workflow | Line | Issue | Fix Strategy |
|----------|------|-------|--------------|
| [playwright.yml](.github/workflows/playwright.yml) | 103 | `head_branch` used directly as tag | `tr '/' '-'` sanitization |
| [playwright.yml](.github/workflows/playwright.yml) | 161 | `head_branch` in artifact name | Add sanitize step |
| [supply-chain-verify.yml](.github/workflows/supply-chain-verify.yml) | 74 | Only hardcodes `feature/beta-release` | Generic feature/* handling with `tr '/' '-'` |
| [supply-chain-pr.yml](.github/workflows/supply-chain-pr.yml) | 196 | `head_branch` in artifact name | Add sanitize step |
---
## Execution Checklist
- [ ] **Fix 1**: Update `playwright.yml` line 103 - sanitize branch name for Docker tag
- [ ] **Fix 2**: Update `playwright.yml` line 161 - sanitize branch name for artifact
- [ ] **Fix 3**: Update `supply-chain-verify.yml` lines 74-75 - generic feature branch handling
- [ ] **Fix 4**: Update `supply-chain-pr.yml` line 196 - sanitize branch name for artifact
- [ ] **Verify**: Push to `feature/beta-release` and confirm workflows pass
- [ ] **CI**: All affected workflows should complete without "invalid reference format"
---
## Verification
After applying fixes:
```bash
# Test sanitization logic locally
echo "feature/beta-release" | tr '/' '-'
# Expected output: feature-beta-release
# Verify Docker accepts the sanitized tag
docker pull ghcr.io/owner/charon:feature-beta-release
# Should work (or fail with 404 if not published yet, but NOT "invalid reference format")
```
---
## References
- [Docker tag naming rules](https://docs.docker.com/engine/reference/commandline/tag/)
- [docker/metadata-action type=ref behavior](https://github.com/docker/metadata-action#typeref)
- GitHub Issue: Workflow failures on `feature/beta-release` branch
---
# WAF-2026-001: wget-style curl Syntax Migration (Archived)
**Plan ID**: WAF-2026-001
**Status**: 📋 PENDING
**Status**: ✅ ARCHIVED (Superseded by WAF-2026-002 as current active plan)
**Priority**: High
**Created**: 2026-01-25
**Scope**: Fix integration test scripts using incorrect wget-style curl syntax