|
| 1 | +name: "Run vCluster Ginkgo E2E Tests" |
| 2 | +description: "Execute Ginkgo-based e2e tests with support for both directory-based and label-based filtering" |
| 3 | +inputs: |
| 4 | + image: |
| 5 | + description: "Docker image to use for testing" |
| 6 | + required: true |
| 7 | + timeout: |
| 8 | + description: "Test timeout" |
| 9 | + required: false |
| 10 | + default: "40m" |
| 11 | + # Test selection strategy - mutually exclusive |
| 12 | + test-dir: |
| 13 | + description: "Directory containing tests relative to e2e-next/ (for directory-based testing)" |
| 14 | + required: false |
| 15 | + default: "" |
| 16 | + ginkgo-label: |
| 17 | + description: "Ginkgo label to filter tests (for label-based testing)" |
| 18 | + required: false |
| 19 | + default: "" |
| 20 | + e2e-dir: |
| 21 | + description: "E2E directory containing all test suites" |
| 22 | + required: false |
| 23 | + default: "e2e-next" |
| 24 | + |
| 25 | +outputs: |
| 26 | + failure-summary: |
| 27 | + description: "Summary of test failures (if any)" |
| 28 | + value: ${{ steps.generate-summary.outputs.failure-summary }} |
| 29 | + |
| 30 | +runs: |
| 31 | + using: "composite" |
| 32 | + steps: |
| 33 | + - name: Validate inputs |
| 34 | + shell: bash |
| 35 | + run: | |
| 36 | + if [[ -z "${{ inputs.test-dir }}" && -z "${{ inputs.ginkgo-label }}" ]]; then |
| 37 | + echo "Error: Either test-dir or ginkgo-label must be provided" |
| 38 | + exit 1 |
| 39 | + fi |
| 40 | +
|
| 41 | + if [[ -n "${{ inputs.test-dir }}" && -n "${{ inputs.ginkgo-label }}" ]]; then |
| 42 | + echo "Error: test-dir and ginkgo-label are mutually exclusive" |
| 43 | + exit 1 |
| 44 | + fi |
| 45 | +
|
| 46 | + - name: Download vcluster cli |
| 47 | + uses: actions/download-artifact@v6 |
| 48 | + with: |
| 49 | + name: vcluster |
| 50 | + |
| 51 | + - name: Download syncer image |
| 52 | + uses: actions/download-artifact@v6 |
| 53 | + with: |
| 54 | + name: vcluster_syncer |
| 55 | + |
| 56 | + - name: Install Ginkgo CLI |
| 57 | + shell: bash |
| 58 | + run: | |
| 59 | + cd "${{ inputs.e2e-dir }}" |
| 60 | + go install github.com/onsi/ginkgo/v2/ginkgo |
| 61 | +
|
| 62 | + - name: Clean up docker images |
| 63 | + shell: bash |
| 64 | + run: | |
| 65 | + # Clean up docker images to free space |
| 66 | + docker image prune --all --force --filter="label!=PRUNE=false" |
| 67 | +
|
| 68 | + - name: Load syncer image |
| 69 | + shell: bash |
| 70 | + run: | |
| 71 | + docker load --input vcluster_syncer |
| 72 | + chmod +x vcluster && sudo mv vcluster /usr/bin |
| 73 | + docker image ls --all |
| 74 | +
|
| 75 | + - name: Execute Ginkgo tests |
| 76 | + shell: bash |
| 77 | + run: | |
| 78 | + set -x |
| 79 | + # Get absolute workspace path |
| 80 | + WORKSPACE_ROOT="$(pwd)" |
| 81 | + echo "Workspace root: ${WORKSPACE_ROOT}" |
| 82 | +
|
| 83 | + REPORTS_DIR="${WORKSPACE_ROOT}/test-reports" |
| 84 | + mkdir -p "${REPORTS_DIR}" |
| 85 | +
|
| 86 | + # Export for use in subsequent steps |
| 87 | + echo "REPORTS_DIR=${REPORTS_DIR}" >> $GITHUB_ENV |
| 88 | + echo "Report directory set to: ${REPORTS_DIR}" |
| 89 | +
|
| 90 | + if [[ -n "${{ inputs.test-dir }}" ]]; then |
| 91 | + echo "Running directory-based tests in: ${{ inputs.test-dir }}" |
| 92 | + TEST_STRATEGY="directory" |
| 93 | + WORKING_DIR="${{ inputs.e2e-dir }}/${{ inputs.test-dir }}" |
| 94 | + # Relative path from test-dir to workspace root |
| 95 | + REPORT_PATH="../../test-reports/report.json" |
| 96 | + else |
| 97 | + echo "Running label-based tests with filter: ${{ inputs.ginkgo-label }}" |
| 98 | + TEST_STRATEGY="label" |
| 99 | + WORKING_DIR="${{ inputs.e2e-dir }}" |
| 100 | + # Relative path from e2e-dir to workspace root |
| 101 | + REPORT_PATH="../test-reports/report.json" |
| 102 | + fi |
| 103 | +
|
| 104 | + # Trim whitespaces and newlines from label filter |
| 105 | + LABEL_FILTER=$(echo "${{ inputs.ginkgo-label }}" | awk '{$1=$1; print}') |
| 106 | +
|
| 107 | + # Build ginkgo command - temporarily disable json-report due to nil pointer issue |
| 108 | + # TODO: Investigate why --json-report causes panic with custom e2e framework |
| 109 | + GINKGO_ARGS=( |
| 110 | + "run" |
| 111 | + "--timeout=${{ inputs.timeout }}" |
| 112 | + "--fail-fast" |
| 113 | + "--show-node-events" |
| 114 | + "--poll-progress-after=20s" |
| 115 | + "--poll-progress-interval=10s" |
| 116 | + "--github-output" |
| 117 | + "--json-report=${REPORT_PATH}" |
| 118 | + "-v" |
| 119 | + ) |
| 120 | +
|
| 121 | + # Add strategy-specific flags |
| 122 | + if [[ "$TEST_STRATEGY" == "label" ]]; then |
| 123 | + GINKGO_ARGS+=("--label-filter=${LABEL_FILTER} || pr") |
| 124 | + GINKGO_ARGS+=("-r") |
| 125 | + fi |
| 126 | +
|
| 127 | + echo "Working directory: ${WORKING_DIR}" |
| 128 | + echo "Test strategy: ${TEST_STRATEGY}" |
| 129 | + echo "Report path: ${REPORT_PATH}" |
| 130 | + echo "Command: ginkgo ${GINKGO_ARGS[*]} ." |
| 131 | +
|
| 132 | + # Run tests |
| 133 | + cd "${WORKING_DIR}" |
| 134 | + echo "Running tests from: $(pwd)" |
| 135 | +
|
| 136 | + ginkgo "${GINKGO_ARGS[@]}" . -- --vcluster-image="${{ inputs.image }}" --teardown=false |
| 137 | +
|
| 138 | + - name: Generate failure summary |
| 139 | + id: generate-summary |
| 140 | + if: always() # Run even if tests failed |
| 141 | + shell: bash |
| 142 | + run: | |
| 143 | + # Generate failure summary if JSON report exists |
| 144 | + if [[ -f "test-reports/report.json" ]]; then |
| 145 | + echo "Generating failure summary from JSON report..." |
| 146 | +
|
| 147 | + # Extract test statistics and failures |
| 148 | + STATS=$(jq -r ' |
| 149 | + { |
| 150 | + failed: ([.[].SpecReports[] | select(.State == "failed")] | length), |
| 151 | + passed: ([.[].SpecReports[] | select(.State == "passed")] | length), |
| 152 | + skipped: ([.[].SpecReports[] | select(.State == "skipped")] | length), |
| 153 | + total_specs: (.[0].PreRunStats.TotalSpecs // 0), |
| 154 | + specs_to_run: (.[0].PreRunStats.SpecsThatWillRun // 0), |
| 155 | + runtime: ((.[0].RunTime // 0) / 1000000000 | floor) |
| 156 | + } |
| 157 | + ' test-reports/report.json) |
| 158 | +
|
| 159 | + FAILED_COUNT=$(echo "$STATS" | jq -r '.failed') |
| 160 | + PASSED_COUNT=$(echo "$STATS" | jq -r '.passed') |
| 161 | + SKIPPED_COUNT=$(echo "$STATS" | jq -r '.skipped') |
| 162 | + TOTAL_SPECS=$(echo "$STATS" | jq -r '.total_specs') |
| 163 | + SPECS_TO_RUN=$(echo "$STATS" | jq -r '.specs_to_run') |
| 164 | + RUNTIME=$(echo "$STATS" | jq -r '.runtime') |
| 165 | +
|
| 166 | + echo "failure-summary<<EOF" >> $GITHUB_OUTPUT |
| 167 | +
|
| 168 | + if [[ "$FAILED_COUNT" -gt 0 ]]; then |
| 169 | + echo "*Test Results Summary:*" >> $GITHUB_OUTPUT |
| 170 | + echo "📊 Executed: $SPECS_TO_RUN/$TOTAL_SPECS tests" >> $GITHUB_OUTPUT |
| 171 | + echo "❌ Failed: $FAILED_COUNT" >> $GITHUB_OUTPUT |
| 172 | + echo "✅ Passed: $PASSED_COUNT" >> $GITHUB_OUTPUT |
| 173 | + if [[ "$SKIPPED_COUNT" -gt 0 ]]; then |
| 174 | + echo "⏭️ Skipped: $SKIPPED_COUNT" >> $GITHUB_OUTPUT |
| 175 | + fi |
| 176 | + echo "⏱️ Duration: ${RUNTIME}s" >> $GITHUB_OUTPUT |
| 177 | + echo "" >> $GITHUB_OUTPUT |
| 178 | + echo "*Failed Tests:*" >> $GITHUB_OUTPUT |
| 179 | +
|
| 180 | + # Extract failed test details |
| 181 | + jq -r '[.[].SpecReports[] | select(.State == "failed")] | |
| 182 | + .[] | |
| 183 | + "❌ [FAIL] [\(.LeafNodeType)]" + |
| 184 | + (if .ContainerHierarchyTexts then " " + (.ContainerHierarchyTexts | join(" ")) else "" end) + |
| 185 | + (if .LeafNodeText != "" then " " + .LeafNodeText else "" end) + |
| 186 | + "\n 📍 " + .LeafNodeLocation.FileName + ":" + (.LeafNodeLocation.LineNumber | tostring)' \ |
| 187 | + test-reports/report.json >> $GITHUB_OUTPUT |
| 188 | + else |
| 189 | + echo "*Test Results Summary:*" >> $GITHUB_OUTPUT |
| 190 | + echo "📊 Executed: $SPECS_TO_RUN/$TOTAL_SPECS tests" >> $GITHUB_OUTPUT |
| 191 | + echo "✅ All tests passed! ($PASSED_COUNT/$SPECS_TO_RUN)" >> $GITHUB_OUTPUT |
| 192 | + if [[ "$SKIPPED_COUNT" -gt 0 ]]; then |
| 193 | + echo "⏭️ Skipped: $SKIPPED_COUNT" >> $GITHUB_OUTPUT |
| 194 | + fi |
| 195 | + echo "⏱️ Duration: ${RUNTIME}s" >> $GITHUB_OUTPUT |
| 196 | + fi |
| 197 | +
|
| 198 | + echo "EOF" >> $GITHUB_OUTPUT |
| 199 | +
|
| 200 | + echo "✅ Failure summary generated (Failed: $FAILED_COUNT, Passed: $PASSED_COUNT)" |
| 201 | + else |
| 202 | + echo "ℹ️ JSON report not found (currently disabled due to compatibility issues)" |
| 203 | + echo "failure-summary=JSON reporting temporarily disabled - tests ran successfully, check output above for results" >> $GITHUB_OUTPUT |
| 204 | + fi |
0 commit comments