-
Notifications
You must be signed in to change notification settings - Fork 993
Add golden artifact generation to nightly backend test suite #17663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
de9c876
dc2c80d
57e93cf
4eaeabc
4226112
cfbbf25
7038965
ff2dbda
af61150
364c7f1
9756b37
64f5ae8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,7 +85,10 @@ else | |
| fi | ||
| CMAKE_ARGS="$EXTRA_BUILD_ARGS" ${CONDA_RUN_CMD} $SETUP_SCRIPT --build-tool cmake --build-mode Release --editable true | ||
|
|
||
| GOLDEN_DIR="${ARTIFACT_DIR}/golden-artifacts" | ||
| export GOLDEN_ARTIFACTS_DIR="${GOLDEN_DIR}" | ||
|
|
||
| EXIT_CODE=0 | ||
| ${CONDA_RUN_CMD} pytest -c /dev/nul -n auto backends/test/suite/$SUITE/ -m flow_$FLOW --json-report --json-report-file="$REPORT_FILE" || EXIT_CODE=$? | ||
| ${CONDA_RUN_CMD} pytest -c /dev/null -n auto backends/test/suite/$SUITE/ -m flow_$FLOW --json-report --json-report-file="$REPORT_FILE" || EXIT_CODE=$? | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. haha |
||
| # Generate markdown summary. | ||
| ${CONDA_RUN_CMD} python -m executorch.backends.test.suite.generate_markdown_summary_json "$REPORT_FILE" > ${GITHUB_STEP_SUMMARY:-"step_summary.md"} --exit-code $EXIT_CODE | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -59,6 +59,61 @@ jobs: | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| source .ci/scripts/test_backend.sh "${{ matrix.suite }}" "${{ matrix.flow }}" "${RUNNER_ARTIFACT_DIR}" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| package-golden-artifacts: | ||||||||||||||||||||||||||
| if: ${{ inputs.run-linux }} | ||||||||||||||||||||||||||
| needs: test-backend-linux | ||||||||||||||||||||||||||
| runs-on: linux.2xlarge | ||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||
| - name: Download model test artifacts | ||||||||||||||||||||||||||
| uses: actions/download-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| pattern: test-report-*-models | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| pattern: test-report-*-models | |
| pattern: test-report-* |
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The shell command uses a glob pattern that could fail silently if there are no matching files. The copy command with 2>/dev/null || true suppresses all errors, which could hide legitimate issues like permission problems or disk space errors. Consider checking if the source files exist before attempting to copy, and only suppress the expected "file not found" error.
| cp "$flow_dir"/*.pte "$flow_dir"/*_input*.bin "$flow_dir"/*_expected_output*.bin \ | |
| "golden_combined/${flow_name}/" 2>/dev/null || true | |
| cp_sources=() | |
| for pattern in "$flow_dir"/*.pte "$flow_dir"/*_input*.bin "$flow_dir"/*_expected_output*.bin; do | |
| for f in $pattern; do | |
| [ -e "$f" ] || continue | |
| cp_sources+=("$f") | |
| done | |
| done | |
| if [ "${#cp_sources[@]}" -gt 0 ]; then | |
| cp "${cp_sources[@]}" "golden_combined/${flow_name}/" | |
| fi |
Copilot
AI
Feb 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR description mentions "These artifacts are packaged into per-model zips and a combined golden_artifacts_yymmddhh.zip", but the implementation only creates a combined zip file (line 92). There are no per-model zips being created. Either update the PR description to match the implementation, or add the per-model zip creation step if it was intended.
Copilot
AI
Feb 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition checks for the existence of golden_artifacts_*.zip files to determine whether to upload to S3, but this check happens in the step itself (line 98). If for some reason the file doesn't exist at that point, the step will be skipped silently. However, the step name suggests it should "Upload golden artifacts to S3" unconditionally if the package-golden-artifacts job succeeded. Consider whether the conditional should be on the job level (line 63) rather than the step level, or if the conditional logic needs adjustment to match the intended behavior.
| if: ${{ hashFiles('golden_artifacts_*.zip') != '' }} |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,8 @@ | |||||||||
| # This source code is licensed under the BSD-style license found in the | ||||||||||
| # LICENSE file in the root directory of this source tree. | ||||||||||
|
|
||||||||||
| import logging | ||||||||||
| import os | ||||||||||
| import random | ||||||||||
| from collections import Counter, OrderedDict | ||||||||||
| from typing import Any, Callable, Dict, List, Optional, Tuple | ||||||||||
|
|
@@ -317,11 +319,14 @@ def run_method_and_compare_outputs( | |||||||||
| rtol=1e-03, | ||||||||||
| qtol=0, | ||||||||||
| statistics_callback: Callable[[ErrorStatistics], None] | None = None, | ||||||||||
| artifact_dir: Optional[str] = None, | ||||||||||
| artifact_name: Optional[str] = None, | ||||||||||
| ): | ||||||||||
| number_of_runs = 1 if inputs is not None else num_runs | ||||||||||
| reference_stage = self.stages[StageType.EXPORT] | ||||||||||
|
|
||||||||||
| stage = stage or self.cur | ||||||||||
| artifacts_saved = False | ||||||||||
|
|
||||||||||
| for _ in range(number_of_runs): | ||||||||||
| inputs_to_run = inputs if inputs else next(self.generate_random_inputs()) | ||||||||||
|
|
@@ -346,8 +351,54 @@ def run_method_and_compare_outputs( | |||||||||
| statistics_callback, | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| if artifact_dir and artifact_name and not artifacts_saved: | ||||||||||
| try: | ||||||||||
| self._dump_golden_artifacts( | ||||||||||
| artifact_dir, | ||||||||||
| artifact_name, | ||||||||||
| inputs_to_run, | ||||||||||
| reference_output, | ||||||||||
| ) | ||||||||||
| except Exception: | ||||||||||
| logging.getLogger(__name__).warning( | ||||||||||
| f"Failed to dump golden artifacts for {artifact_name}", | ||||||||||
| exc_info=True, | ||||||||||
| ) | ||||||||||
| artifacts_saved = True | ||||||||||
|
|
||||||||||
| return self | ||||||||||
|
|
||||||||||
| @staticmethod | ||||||||||
| def _dump_golden_artifacts( | ||||||||||
| artifact_dir: str, | ||||||||||
| artifact_name: str, | ||||||||||
| inputs: Tuple[torch.Tensor], | ||||||||||
| reference_output, | ||||||||||
| ): | ||||||||||
| logger = logging.getLogger(__name__) | ||||||||||
| os.makedirs(artifact_dir, exist_ok=True) | ||||||||||
|
||||||||||
|
|
||||||||||
| for i, inp in enumerate(inputs): | ||||||||||
| if isinstance(inp, torch.Tensor): | ||||||||||
| suffix = "" if len(inputs) == 1 else f"_{i}" | ||||||||||
| path = os.path.join(artifact_dir, f"{artifact_name}_input{suffix}.bin") | ||||||||||
| inp.contiguous().numpy().tofile(path) | ||||||||||
| logger.info(f"Saved golden input to {path}") | ||||||||||
|
Comment on lines
+381
to
+386
|
||||||||||
|
|
||||||||||
| if isinstance(reference_output, torch.Tensor): | ||||||||||
| reference_output = (reference_output,) | ||||||||||
| elif isinstance(reference_output, OrderedDict): | ||||||||||
| reference_output = tuple(reference_output.values()) | ||||||||||
|
||||||||||
| reference_output = tuple(reference_output.values()) | |
| reference_output = tuple(reference_output.values()) | |
| elif isinstance(reference_output, (list, tuple)): | |
| reference_output = tuple(reference_output) |
Copilot
AI
Feb 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the input handling, the loop only saves outputs that are torch.Tensor instances. If reference_output contains non-tensor elements after being converted to a tuple, those elements will be silently skipped. This could result in incomplete output files. Consider logging a warning when non-tensor outputs are encountered and skipped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GOLDEN_ARTIFACTS_DIRis exported unconditionally, so the operators suite will also generate golden inputs/outputs and.ptefiles even though the packaging job only collects*-modelsartifacts. This will increase artifact size and I/O for operators runs; consider only setting this env var (or only zipping) whenSUITE=models(or when a separate opt-in flag is set).