Merge branch 'feature/beta-release' into renovate/feature/beta-release-golang.org-x-net-0.x

This commit is contained in:
Jeremy
2026-01-13 15:28:56 -05:00
committed by GitHub
6 changed files with 1205 additions and 7 deletions

View File

@@ -41,7 +41,7 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4
uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4
with:
languages: ${{ matrix.language }}
# Use CodeQL config to exclude documented false positives
@@ -57,10 +57,10 @@ jobs:
cache-dependency-path: backend/go.sum
- name: Autobuild
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4
uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4
uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4
with:
category: "/language:${{ matrix.language }}"

View File

@@ -363,7 +363,7 @@ jobs:
- name: Upload Trivy results
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true' && steps.trivy-check.outputs.exists == 'true'
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
with:
sarif_file: 'trivy-results.sarif'
token: ${{ secrets.GITHUB_TOKEN }}
@@ -642,7 +642,7 @@ jobs:
# Critical Fix #3: SARIF category includes SHA to prevent conflicts
- name: Upload SARIF to GitHub Security
if: always()
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
with:
sarif_file: grype-results.sarif
category: supply-chain-pr-${{ github.event.pull_request.number }}-${{ github.sha }}
@@ -793,3 +793,113 @@ jobs:
issue_number: context.issue.number,
body: body
});
# ============================================================================
# E2E Tests (Playwright) for PR Builds
# ============================================================================
# This job runs end-to-end tests using Playwright against the Docker image
# built for pull requests. It validates the application's functionality from
# the user's perspective before merging.
#
# Dependency Chain: build-and-push → e2e-tests-pr
# ============================================================================
e2e-tests-pr:
name: E2E Tests (Playwright)
needs: build-and-push
runs-on: ubuntu-latest
timeout-minutes: 15
if: |
github.event_name == 'pull_request' &&
needs.build-and-push.outputs.skip_build != 'true' &&
needs.build-and-push.result == 'success'
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Download Docker image artifact
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: pr-image-${{ github.event.pull_request.number }}
- name: Load Docker image
run: |
echo "📦 Loading image from artifact..."
docker load -i charon-pr-image.tar
echo "✅ Image loaded successfully"
- name: Normalize image name
run: |
IMAGE_NAME=$(echo "${{ github.repository_owner }}/charon" | tr '[:upper:]' '[:lower:]')
echo "IMAGE_NAME=${IMAGE_NAME}" >> $GITHUB_ENV
- name: Verify loaded image
run: |
IMAGE_REF="ghcr.io/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}"
if ! docker image inspect "${IMAGE_REF}" >/dev/null 2>&1; then
echo "❌ ERROR: Image not found: ${IMAGE_REF}"
docker images
exit 1
fi
echo "✅ Image loaded: ${IMAGE_REF}"
- name: Start application container
run: |
IMAGE_REF="ghcr.io/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}"
docker run -d --name charon \
-p 8080:8080 \
-e CHARON_ENV=development \
-e CHARON_DEBUG=1 \
-e CHARON_ENCRYPTION_KEY=test-key-for-ci-only-not-production \
"${IMAGE_REF}"
- name: Wait for application health
run: |
echo "Waiting for application to be ready..."
timeout 120 bash -c 'until curl -sf http://localhost:8080/api/v1/health > /dev/null; do
echo "Waiting for health endpoint..."
sleep 2
done'
echo "✅ Application is ready"
- name: Setup Node.js
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6
with:
node-version: lts/*
- name: Install Playwright dependencies
run: |
npm ci
npx playwright install --with-deps
- name: Run Playwright E2E tests
env:
PLAYWRIGHT_BASE_URL: http://localhost:8080
run: npx playwright test
- name: Stop application container
if: always()
run: docker stop charon && docker rm charon
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: playwright-report-pr-${{ github.event.pull_request.number }}
path: playwright-report/
retention-days: 7
- name: Create E2E Test Summary
if: always()
run: |
echo "## 🎭 E2E Test Results - PR #${{ github.event.pull_request.number }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image**: \`ghcr.io/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Status**: ${{ job.status == 'success' && '✅ All tests passed' || '❌ Tests failed' }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [[ "${{ job.status }}" != "success" ]]; then
echo "📊 [View Test Report](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}#artifacts)" >> $GITHUB_STEP_SUMMARY
fi

View File

@@ -1,4 +1,14 @@
name: Playwright Tests
# ============================================================================
# DISABLED: This workflow has been integrated into docker-build.yml
# ============================================================================
# Integration date: January 12, 2026
# Reason: Consolidated E2E testing with Docker build workflow for better
# visibility and to ensure tests run against the actual built image.
#
# See: .github/workflows/docker-build.yml → e2e-tests-pr job
# ============================================================================
name: Playwright Tests (DISABLED)
on:
push:
branches: [ main, master ]

View File

@@ -105,7 +105,7 @@ jobs:
severity: 'CRITICAL,HIGH,MEDIUM'
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
with:
sarif_file: 'trivy-weekly-results.sarif'

View File

@@ -897,3 +897,66 @@ func TestImportHandler_UploadMulti(t *testing.T) {
assert.Contains(t, resp["error"], "empty")
})
}
// Additional tests for comprehensive coverage
func TestImportHandler_Cancel_MissingSessionUUID(t *testing.T) {
gin.SetMode(gin.TestMode)
db := setupImportTestDB(t)
handler := handlers.NewImportHandler(db, "echo", "/tmp", "")
router := gin.New()
router.DELETE("/import/cancel", handler.Cancel)
// Missing session_uuid parameter
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/import/cancel", http.NoBody)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusBadRequest, w.Code)
var resp map[string]any
_ = json.Unmarshal(w.Body.Bytes(), &resp)
assert.Equal(t, "session_uuid required", resp["error"])
}
func TestImportHandler_Cancel_InvalidSessionUUID(t *testing.T) {
gin.SetMode(gin.TestMode)
db := setupImportTestDB(t)
handler := handlers.NewImportHandler(db, "echo", "/tmp", "")
router := gin.New()
router.DELETE("/import/cancel", handler.Cancel)
// Test "." which becomes empty after filepath.Base processing
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/import/cancel?session_uuid=.", http.NoBody)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusBadRequest, w.Code)
var resp map[string]any
_ = json.Unmarshal(w.Body.Bytes(), &resp)
assert.Equal(t, "invalid session_uuid", resp["error"])
}
func TestImportHandler_Commit_InvalidSessionUUID(t *testing.T) {
gin.SetMode(gin.TestMode)
db := setupImportTestDB(t)
handler := handlers.NewImportHandler(db, "echo", "/tmp", "")
router := gin.New()
router.POST("/import/commit", handler.Commit)
// Test "." which becomes empty after filepath.Base processing
payload := map[string]any{
"session_uuid": ".",
"resolutions": map[string]string{},
}
body, _ := json.Marshal(payload)
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/import/commit", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusBadRequest, w.Code)
var resp map[string]any
_ = json.Unmarshal(w.Body.Bytes(), &resp)
assert.Equal(t, "invalid session_uuid", resp["error"])
}

File diff suppressed because it is too large Load Diff