Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 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
54 changes: 54 additions & 0 deletions .github/actions/codecov-merge-upload/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: 'Codecov Download and Upload'
description: 'Download coverage artifact from previous PR run and upload to Codecov'

inputs:
artifact-name:
description: 'Name of the coverage artifact'
required: false
default: 'pr-build'
coverage-path:
description: 'Path to coverage files'
required: true
workflow-path:
description: 'Path to workflow file for artifact lookup'
required: true
override-commit:
description: 'Commit SHA to override in Codecov'
required: true
codecov-token:
description: 'Codecov token for uploading'
required: true
github-token:
description: 'GitHub token for artifact operations'
required: true

runs:
using: 'composite'
steps:
- name: Find latest successful PR run for this commit
id: find-run
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.github-token }}
REPO: ${{ github.repository }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
CURRENT_RUN_ID: ${{ github.run_id }}
ARTIFACT_NAME: ${{ inputs.artifact-name }}
WORKFLOW_PATH: ${{ inputs.workflow-path }}
run: ./.github/scripts/find-codecov-artifact.sh
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Download coverage artifact from previous run
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact-name }}
run-id: ${{ steps.find-run.outputs.run_id }}
github-token: ${{ inputs.github-token }}
path: ${{ inputs.coverage-path }}

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ inputs.codecov-token }}
override_commit: ${{ inputs.override-commit }}
override_branch: main

35 changes: 35 additions & 0 deletions .github/actions/codecov-upload-pr/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: 'Codecov Upload PR'
description: 'Upload coverage artifacts during PR and send to Codecov'

inputs:
artifact-name:
description: 'Name of the coverage artifact'
required: false
default: 'pr-build'
coverage-path:
description: 'Path to coverage files'
required: true
retention-days:
description: 'Days to retain the artifact'
required: false
default: '7'
codecov-token:
description: 'Codecov token for uploading'
required: true

runs:
using: 'composite'
steps:
- name: Upload artifact for PR
uses: actions/upload-artifact@v4
with:
overwrite: true
name: codecov-pr-build-${{ inputs.artifact-name }}
path: ${{ inputs.coverage-path }}
retention-days: ${{ inputs.retention-days }}

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ inputs.codecov-token }}

88 changes: 88 additions & 0 deletions .github/scripts/find-codecov-artifact.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash

# This script finds the latest successful workflow run artifact for a PR commit.
#
# Required environment variables:
# REPO: GitHub repository (e.g., owner/repo)
# HEAD_SHA: The PR head commit SHA
# CURRENT_RUN_ID: The current workflow run ID
# ARTIFACT_NAME: Name of the artifact to find
# WORKFLOW_PATH: Path to the workflow file to filter by
# GITHUB_TOKEN: Required for API authentication
#
# Outputs (to $GITHUB_OUTPUT):
# run_id: The workflow run ID containing the artifact
# artifact_id: The artifact ID

REPO="${REPO:?REPO environment variable is required}"
HEAD_SHA="${HEAD_SHA:?HEAD_SHA environment variable is required}"
CURRENT_RUN_ID="${CURRENT_RUN_ID:?CURRENT_RUN_ID environment variable is required}"
ARTIFACT_NAME="${ARTIFACT_NAME:?ARTIFACT_NAME environment variable is required}"
WORKFLOW_PATH="${WORKFLOW_PATH:?WORKFLOW_PATH environment variable is required}"

echo "Head SHA: $HEAD_SHA"
echo "Current run id: $CURRENT_RUN_ID"

# Get all PR runs for this commit (since its runs per Sha 500 should be enough for now)
json=$(curl -sf \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/actions/runs?head_sha=$HEAD_SHA&event=pull_request&per_page=500")

if [ $? -ne 0 ]; then
echo "Failed to fetch workflow runs" >&2
exit 1
fi

# Pick the latest *completed & successful* run that is NOT this run
run_id=$(echo "$json" | jq -r --arg cur "$CURRENT_RUN_ID" --arg workflow "$WORKFLOW_PATH" '
.workflow_runs
| map(select(
.id != ($cur|tonumber)
and .status == "completed"
and .conclusion == "success"
and .path == $workflow
))
| sort_by(.created_at)
| last
| .id
')

if [ $? -ne 0 ]; then
echo "Failed to parse workflow runs JSON" >&2
exit 1
fi

if [ -z "$run_id" ] || [ "$run_id" = "null" ]; then
echo "No previous successful PR run found for $HEAD_SHA" >&2
exit 1
fi

echo "Using run id: $run_id"

Comment thread
coderabbitai[bot] marked this conversation as resolved.
# Get artifacts for that run
artifacts_json=$(curl -s \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/actions/runs/$run_id/artifacts")

# Find the artifact ID for the desired artifact name
artifact_id=$(echo "$artifacts_json" | jq -r --arg name "$ARTIFACT_NAME" '
.artifacts
| map(select(.name == $name and .expired == false))
| sort_by(.created_at)
| last
| .id
')

if [ -z "$artifact_id" ] || [ "$artifact_id" = "null" ]; then
echo "No non-expired artifact named '$ARTIFACT_NAME' found for run $run_id" >&2
echo "Artifacts JSON for debugging:" >&2
echo "$artifacts_json" >&2
exit 1
fi

echo "Using artifact id: $artifact_id"

echo "run_id=$run_id" >> "$GITHUB_OUTPUT"
echo "artifact_id=$artifact_id" >> "$GITHUB_OUTPUT"
42 changes: 38 additions & 4 deletions .github/workflows/cli-ci.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: wgc CI
on:
pull_request:
types: [opened, reopened, synchronize, closed]
paths:
- 'pnpm-lock.yaml'
- 'cli/**/*'
Expand All @@ -20,6 +21,7 @@ env:

jobs:
build_test_default:
if: github.event.action != 'closed'
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -54,12 +56,18 @@ jobs:
- name: Get Coverage
run: pnpm run --filter wgc coverage

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
- name: Upload Coverage to Codecov
uses: ./.github/actions/codecov-upload-pr
with:
token: ${{ secrets.CODECOV_TOKEN }}
artifact-name: pr-build
coverage-path: |
cli/coverage/clover.xml
cli/coverage/coverage-final.json
retention-days: 7
codecov-token: ${{ secrets.CODECOV_TOKEN }}

build_test_node_matrix:
if: github.event.action != 'closed'
timeout-minutes: 10
runs-on: ubuntu-latest

Expand Down Expand Up @@ -89,6 +97,7 @@ jobs:
run: bun test e2e --test-name-pattern node

build_bun_matrix:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
timeout-minutes: 30

Expand All @@ -107,11 +116,36 @@ jobs:
build_test:
runs-on: ubuntu-latest
needs: [build_test_default, build_test_node_matrix, build_bun_matrix]
if: always()
if: github.event.action != 'closed' && always()
steps:
- name: 'All tests passed'
if: ${{ !(contains(needs.*.result, 'failure')) }}
run: exit 0
- name: 'Some tests failed'
if: ${{ contains(needs.*.result, 'failure') }}
run: exit 1

post-merge:
if: >
github.event_name == 'pull_request' &&
github.event.action == 'closed' &&
github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}

- name: Print merge commit SHA
run: |
echo "Merge commit SHA: ${{ github.event.pull_request.merge_commit_sha }}"

- name: Download computed artifact and upload to codecov with merge SHA
uses: ./.github/actions/codecov-merge-upload
with:
artifact-name: pr-build
coverage-path: cli/coverage
workflow-path: .github/workflows/cli-ci.yaml
override-commit: ${{ github.event.pull_request.merge_commit_sha }}
codecov-token: ${{ secrets.CODECOV_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
28 changes: 22 additions & 6 deletions .github/workflows/router-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -358,21 +358,37 @@ jobs:
docker exec "$cid" redis-cli -u "redis://cosmo:test@redis-0:6379" ping
docker exec "$cid" redis-cli -u "redis://cosmo:test@redis-0:6379" cluster nodes

- name: Compute artifact name
id: artifact_name
run: |
# Sanitize test target: remove './', replace spaces and special chars with underscores
target="${{ matrix.test_target }}"
sanitized=$(echo "$target" | sed 's|\.\/||g' | sed 's|[^a-zA-Z0-9]|_|g' | sed 's|_\+|_|g' | sed 's|^_||' | sed 's|_$||')
echo "sanitized=$sanitized" >> $GITHUB_OUTPUT

- name: Run Integration tests ${{ matrix.test_target }}
working-directory: ./router-tests
run: make test-coverage test_retry_count=0 test_params="-run '^Test[^(Flaky)]' --timeout=5m -p 1 --parallel 10" test_target="${{ matrix.test_target }}"

- name: Upload integration results to Codecov
uses: ./.github/actions/codecov-upload-pr
with:
artifact-name: router-${{ steps.artifact_name.outputs.sanitized }}-nonFlaky
coverage-path: router-tests/coverage.out
retention-days: 7
codecov-token: ${{ secrets.CODECOV_TOKEN }}

- name: Run Flaky Integration tests ${{ matrix.test_target }}
working-directory: ./router-tests
run: make test-coverage test_retry_count=3 test_params="-run '^TestFlaky' --timeout=5m -p 1 --parallel 10" test_target="${{ matrix.test_target }}"

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
- name: Upload flaky integration results to Codecov
uses: ./.github/actions/codecov-upload-pr
with:
verbose: true
files: |
router-tests/coverage.out
token: ${{ secrets.CODECOV_TOKEN }}
artifact-name: router-${{ steps.artifact_name.outputs.sanitized }}-flaky
coverage-path: router-tests/coverage.out
retention-days: 7
codecov-token: ${{ secrets.CODECOV_TOKEN }}

image_scan:
if: github.event.pull_request.head.repo.full_name == github.repository
Expand Down
5 changes: 5 additions & 0 deletions codecov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ coverage:
target: 90
threshold: 5
informational: true # We don't want to block PRs based on the result
project:
default:
target: 90
threshold: 5
informational: true
Loading