This document provides detailed information about the Binary Testing workflow, which is responsible for testing the binary artifacts produced by the Binary Builder workflow across multiple platforms.
- Overview
- Trigger Conditions
- Environment Variables
- Permissions
- Jobs and Steps
- Test Matrix
- Test Stages
- Issue Creation
- Release Notes Update
- Common Issues and Troubleshooting
The Binary Testing workflow (binary_testing.yaml) is responsible for testing the binary artifacts produced by the Binary Builder workflow. It runs after the Binary Builder workflow completes successfully, downloading the binary artifacts and running a series of tests to ensure they function correctly on each platform.
- Verify that built binaries function correctly on their target platforms
- Test multiple aspects of binary functionality
- Report test results and create issues for failures
- Update release notes with test results
- Ensure high-quality releases across all supported platforms
The workflow is triggered under the following conditions:
on:
workflow_run:
workflows: ["Build and Package Agents-Fun"]
types:
- completed
branches:
- main
- development
workflow_dispatch: # Allow manual triggering- After Binary Builder: Automatically triggered when the "Build and Package Agents-Fun" workflow completes on the main or development branches
- Manual Trigger: Can be manually triggered through the GitHub Actions interface
The workflow defines several global environment variables:
| Variable | Value | Description |
|---|---|---|
BINARY_NAME |
agent_runner | The name of the binary to test |
TEST_TIMEOUT |
60 | Timeout for individual tests in seconds |
These variables are used throughout the workflow to ensure consistent testing.
The workflow follows the principle of least privilege by explicitly defining permissions:
permissions:
contents: read
actions: read
issues: write # Required to create GitHub issues for failed testsThis ensures that the workflow only has the minimum permissions required to perform its tasks.
The workflow consists of three main jobs:
- prepare-testing: Prepares the test matrix based on available artifacts
- test-binaries: Tests each binary on its respective platform
- update-release-notes: Updates release notes with test results
- notify-completion: Notifies of workflow completion
The prepare-testing job:
- Extracts the version from package.json
- Gets information about available artifacts
- Creates a test matrix based on available artifacts
The test-binaries job:
- Downloads the binary artifact for the current matrix combination
- Makes the binary executable (for Linux/macOS)
- Creates a test directory structure with a minimal character file
- Runs a series of tests on the binary
- Generates a test summary
- Creates a GitHub issue for failed tests
The update-release-notes job:
- Downloads test results
- Gets the latest release
- Updates the release notes with test results
The notify-completion job:
- Generates a summary of the workflow results
- Provides a link to the workflow run for more details
The workflow uses a dynamic test matrix based on the available binary artifacts:
strategy:
fail-fast: false # Continue with other tests if one fails
matrix: ${{ fromJson(needs.prepare-testing.outputs.matrix) }}This ensures that each binary is tested on its appropriate platform:
- Linux binaries (x64, arm64) → Tested on Ubuntu
- macOS binaries (x64, arm64) → Tested on macOS
- Windows binaries (x64) → Tested on Windows
Each binary goes through the following test stages:
Verifies that the binary can be executed with the --version flag:
- name: Test binary execution
id: test_execution
shell: bash
run: |
echo "🧪 Testing binary execution..."
# Different command based on OS
if [[ "${{ runner.os }}" == "Windows" ]]; then
# Windows binary
./test-binary/${{ matrix.artifact_name }}.exe --version || exit_code=$?
else
# Linux/macOS binary
./test-binary/${{ matrix.artifact_name }} --version || exit_code=$?
fi
if [[ $exit_code -eq 0 ]]; then
echo "✅ Binary executes successfully"
echo "test_execution=pass" >> $GITHUB_OUTPUT
else
echo "❌ Binary execution failed with exit code: $exit_code"
echo "test_execution=fail" >> $GITHUB_OUTPUT
echo "::error::Binary execution test failed for ${{ matrix.artifact_name }}"
fiConfirms that the reported version matches the expected version from package.json:
- name: Test version output
id: test_version
if: steps.test_execution.outputs.test_execution == 'pass'
shell: bash
run: |
echo "🧪 Testing version output..."
# Get expected version
expected_version="${{ needs.prepare-testing.outputs.version }}"
# Run binary with --version flag and capture output
if [[ "${{ runner.os }}" == "Windows" ]]; then
# Windows binary
version_output=$(./test-binary/${{ matrix.artifact_name }}.exe --version)
else
# Linux/macOS binary
version_output=$(./test-binary/${{ matrix.artifact_name }} --version)
fi
# Check if version output contains expected version
if [[ "$version_output" == *"$expected_version"* ]]; then
echo "✅ Version output matches expected version: $expected_version"
echo "test_version=pass" >> $GITHUB_OUTPUT
else
echo "❌ Version output does not match expected version"
echo "Expected: $expected_version"
echo "Got: $version_output"
echo "test_version=fail" >> $GITHUB_OUTPUT
echo "::error::Version test failed for ${{ matrix.artifact_name }}. Expected $expected_version but got $version_output"
fiTests that the --help flag works correctly:
- name: Test command-line arguments
id: test_arguments
if: steps.test_execution.outputs.test_execution == 'pass'
shell: bash
run: |
echo "🧪 Testing command-line arguments..."
# Run binary with --help flag
if [[ "${{ runner.os }}" == "Windows" ]]; then
# Windows binary
./test-binary/${{ matrix.artifact_name }}.exe --help || exit_code=$?
else
# Linux/macOS binary
./test-binary/${{ matrix.artifact_name }} --help || exit_code=$?
fi
if [[ $exit_code -eq 0 ]]; then
echo "✅ Command-line arguments test passed"
echo "test_arguments=pass" >> $GITHUB_OUTPUT
else
echo "❌ Command-line arguments test failed with exit code: $exit_code"
echo "test_arguments=fail" >> $GITHUB_OUTPUT
echo "::error::Command-line arguments test failed for ${{ matrix.artifact_name }}"
fiValidates that the binary can load a character definition file:
- name: Test character loading
id: test_character
if: steps.test_execution.outputs.test_execution == 'pass'
shell: bash
timeout-minutes: 1
run: |
echo "🧪 Testing character loading..."
# Run binary with character file (with timeout to prevent hanging)
if [[ "${{ runner.os }}" == "Windows" ]]; then
# Windows binary
timeout ${{ env.TEST_TIMEOUT }} ./test-binary/${{ matrix.artifact_name }}.exe --character=characters/test.character.json --test-mode || exit_code=$?
else
# Linux/macOS binary
timeout ${{ env.TEST_TIMEOUT }} ./test-binary/${{ matrix.artifact_name }} --character=characters/test.character.json --test-mode || exit_code=$?
fi
# Exit code 124 means timeout occurred, which is expected for a normal run
if [[ $exit_code -eq 0 || $exit_code -eq 124 ]]; then
echo "✅ Character loading test passed"
echo "test_character=pass" >> $GITHUB_OUTPUT
else
echo "❌ Character loading test failed with exit code: $exit_code"
echo "test_character=fail" >> $GITHUB_OUTPUT
echo "::error::Character loading test failed for ${{ matrix.artifact_name }}"
fiFor failed tests, the workflow automatically creates a GitHub issue:
- name: Create issue for failed tests
if: steps.test_summary.outputs.overall_result == 'fail'
uses: JasonEtco/create-an-issue@e27dddc79c92bc6e4562f268fffa5ed752639abd # v2.9.1
env:
GITHUB_TOKEN: ${{ github.token }}
ARTIFACT_NAME: ${{ matrix.artifact_name }}
OS: ${{ matrix.os }}
TEST_EXECUTION: ${{ steps.test_execution.outputs.test_execution }}
TEST_VERSION: ${{ steps.test_version.outputs.test_version }}
TEST_ARGUMENTS: ${{ steps.test_arguments.outputs.test_arguments }}
TEST_CHARACTER: ${{ steps.test_character.outputs.test_character }}
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
with:
filename: .github/ISSUE_TEMPLATE/binary_test_failure.md
update_existing: true
search_existing: openThe issue includes:
- Binary information (name, platform)
- Test results for each test stage
- Links to the workflow run for more details
- Next steps for resolving the issue
The workflow updates release notes with test results:
- name: Update release notes
run: |
echo "Updating release notes with test results..."
# Get the latest release
release_id=$(curl -s \
-H "Authorization: token ${{ github.token }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/releases/latest" | jq -r '.id')
if [[ -z "$release_id" || "$release_id" == "null" ]]; then
echo "No release found to update"
exit 0
fi
# Get current release notes
current_body=$(curl -s \
-H "Authorization: token ${{ github.token }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/releases/$release_id" | jq -r '.body')
# Append test results
updated_body="${current_body}
## Test Results
| Binary | Status |
| ------ | ------ |"
# Add results for each binary
for job in $(curl -s \
-H "Authorization: token ${{ github.token }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs" | \
jq -r '.jobs[] | select(.name | startswith("Test ")) | .name + ":" + .conclusion'); do
binary_name=$(echo $job | cut -d':' -f1 | sed 's/Test //')
result=$(echo $job | cut -d':' -f2)
if [[ "$result" == "success" ]]; then
status="✅ Passed"
else
status="❌ Failed"
fi
updated_body="${updated_body}
| ${binary_name} | ${status} |"
done
# Update release notes
curl -X PATCH \
-H "Authorization: token ${{ github.token }}" \
-H "Accept: application/vnd.github.v3+json" \
-d "{\"body\": $(echo "$updated_body" | jq -R -s .)}" \
"https://api.github.com/repos/${{ github.repository }}/releases/$release_id"
echo "Release notes updated successfully"This adds a "Test Results" section to the release notes with the status of each binary.
If the workflow cannot find the binary artifact:
- Check that the Binary Builder workflow completed successfully
- Verify the artifact naming convention matches between workflows
- Ensure the artifact retention period hasn't expired (default: 90 days)
If you encounter "Permission denied" errors:
- Ensure the binary has executable permissions (
chmod +xon Linux/macOS) - Check that the workflow has appropriate permissions to access artifacts
If tests are timing out:
- Adjust the
TEST_TIMEOUTenvironment variable in the workflow - Check if the binary is hanging during execution
- Consider adding debug output to identify where the hang occurs
If tests fail only on specific platforms:
- Check for platform-specific dependencies
- Verify that the binary was built correctly for that platform
- Look for platform-specific code paths that might be failing
If issues aren't being created for failed tests:
- Check that the workflow has the
issues: writepermission - Verify that the issue template exists at
.github/ISSUE_TEMPLATE/binary_test_failure.md - Check for rate limiting or other GitHub API issues
If release notes aren't being updated:
- Check that a release exists
- Verify that the workflow has permission to update releases
- Check for GitHub API errors in the workflow logs