chore(deps): bump borsh, solana-program, spl-token-2022-interface, solana-address #163
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Quasar | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| branches: | |
| - main | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| MAX_JOBS: 64 | |
| MIN_PROJECTS_PER_JOB: 4 | |
| MIN_PROJECTS_FOR_MATRIX: 4 | |
| # Force all JavaScript-based actions to use Node.js 24 runtime. | |
| # Node.js 20 actions are deprecated and will stop working June 2026. | |
| # This catches composite actions whose internal dependencies still reference @v4. | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| changes: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: read | |
| outputs: | |
| changed_projects: ${{ steps.analyze.outputs.changed_projects }} | |
| total_projects: ${{ steps.analyze.outputs.total_projects }} | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 2 | |
| - uses: dorny/paths-filter@v4 | |
| id: changes | |
| if: github.event_name == 'pull_request' | |
| with: | |
| list-files: shell | |
| filters: | | |
| quasar: | |
| - added|modified: '**/quasar/**' | |
| workflow: | |
| - added|modified: '.github/workflows/quasar.yml' | |
| - name: Analyze Changes | |
| id: analyze | |
| run: | | |
| # Generate ignore pattern, excluding comments | |
| ignore_pattern=$(grep -v '^#' .github/.ghaignore | grep -v '^$' | tr '\n' '|' | sed 's/|$//') | |
| echo "Ignore pattern: $ignore_pattern" | |
| # Single source of truth for "what is a framework project": a directory | |
| # whose name is exactly "quasar". `find -type d -name quasar` gives us | |
| # that by construction — no substring matching, no path-segment trickery, | |
| # so siblings like "quasar-example/" can never enter the build list. | |
| function get_projects() { | |
| find . -type d -name "quasar" | grep -vE "$ignore_pattern" | sort | |
| } | |
| # Filter the full project list down to projects touched by the given | |
| # changed files. A file "touches" a project iff it lives inside that | |
| # project directory (prefix match on "<project>/"). This is an | |
| # intersection against get_projects(), so the result is always a subset | |
| # of the authoritative project list. | |
| function filter_by_changes() { | |
| local all_projects="$1" | |
| shift | |
| local changed_files=("$@") | |
| echo "$all_projects" | while read -r project; do | |
| [ -z "$project" ] && continue | |
| local project_prefix="${project#./}/" | |
| for file in "${changed_files[@]}"; do | |
| if [[ "$file" == "$project_prefix"* ]]; then | |
| echo "$project" | |
| break | |
| fi | |
| done | |
| done | sort -u | |
| } | |
| # Determine which projects to build and test | |
| if [[ "${{ github.event_name }}" == "schedule" || "${{ steps.changes.outputs.workflow }}" == "true" ]]; then | |
| # Workflow file changed or schedule — build everything | |
| projects=$(get_projects) | |
| elif [[ "${{ github.event_name }}" == "push" ]]; then | |
| # On push, only build projects with changes since parent commit | |
| mapfile -t changed_files < <(git diff --name-only HEAD~1 HEAD 2>/dev/null || true) | |
| if [ ${#changed_files[@]} -eq 0 ]; then | |
| projects=$(get_projects) | |
| else | |
| projects=$(filter_by_changes "$(get_projects)" "${changed_files[@]}") | |
| fi | |
| elif [[ "${{ steps.changes.outputs.quasar }}" == "true" ]]; then | |
| changed_files=(${{ steps.changes.outputs.quasar_files }}) | |
| projects=$(filter_by_changes "$(get_projects)" "${changed_files[@]}") | |
| else | |
| projects="" | |
| fi | |
| # Output project information | |
| if [[ -n "$projects" ]]; then | |
| echo "Projects to build and test" | |
| echo "$projects" | |
| total_projects=$(echo "$projects" | wc -l) | |
| echo "Total projects: $total_projects" | |
| echo "total_projects=$total_projects" >> $GITHUB_OUTPUT | |
| echo "changed_projects=$(echo "$projects" | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT | |
| else | |
| echo "No projects to build and test." | |
| echo "total_projects=0" >> $GITHUB_OUTPUT | |
| echo "changed_projects=[]" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Generate matrix | |
| id: matrix | |
| run: | | |
| total_projects=${{ steps.analyze.outputs.total_projects }} | |
| max_jobs=${{ env.MAX_JOBS }} | |
| min_projects_per_job=${{ env.MIN_PROJECTS_PER_JOB }} | |
| min_projects_for_matrix=${{ env.MIN_PROJECTS_FOR_MATRIX }} | |
| if [ "$total_projects" -lt "$min_projects_for_matrix" ]; then | |
| echo "matrix=[0]" >> $GITHUB_OUTPUT | |
| else | |
| projects_per_job=$(( (total_projects + max_jobs - 1) / max_jobs )) | |
| projects_per_job=$(( projects_per_job > min_projects_per_job ? projects_per_job : min_projects_per_job )) | |
| num_jobs=$(( (total_projects + projects_per_job - 1) / projects_per_job )) | |
| indices=$(seq 0 $(( num_jobs - 1 ))) | |
| echo "matrix=[$(echo $indices | tr ' ' ',')]" >> $GITHUB_OUTPUT | |
| fi | |
| build-and-test: | |
| needs: changes | |
| if: needs.changes.outputs.total_projects != '0' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| index: ${{ fromJson(needs.changes.outputs.matrix) }} | |
| name: build-and-test-group-${{ matrix.index }} | |
| outputs: | |
| failed_projects: ${{ steps.set-failed.outputs.failed_projects }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Setup sccache | |
| uses: mozilla-actions/sccache-action@v0.0.9 | |
| - name: Configure sccache | |
| run: | | |
| echo "SCCACHE_GHA_ENABLED=true" >> $GITHUB_ENV | |
| echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV | |
| - name: Cache Cargo registry and git | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.toml', '**/Cargo.lock') }} | |
| restore-keys: | | |
| cargo-${{ runner.os }}- | |
| - name: Setup build environment | |
| id: setup | |
| run: | | |
| # Create the build and test function | |
| cat << 'EOF' > build_and_test.sh | |
| function build_and_test() { | |
| local project=$1 | |
| local solana_version=$2 | |
| echo "Building and Testing $project with Solana $solana_version" | |
| cd "$project" || return 1 | |
| # Build with quasar CLI | |
| if ! quasar build; then | |
| echo "::error::quasar build failed for $project" | |
| echo "$project: quasar build failed with $solana_version" >> $GITHUB_WORKSPACE/failed_projects.txt | |
| cd - > /dev/null | |
| return 1 | |
| fi | |
| # Run Rust tests (quasar examples use cargo test with quasar-svm) | |
| if ! cargo test; then | |
| echo "::error::cargo test failed for $project" | |
| echo "$project: cargo test failed with $solana_version" >> $GITHUB_WORKSPACE/failed_projects.txt | |
| cd - > /dev/null | |
| return 1 | |
| fi | |
| echo "Build and tests succeeded for $project with $solana_version version." | |
| cd - > /dev/null | |
| return 0 | |
| } | |
| function process_projects() { | |
| local solana_version=$1 | |
| readarray -t all_projects < <(echo '${{ needs.changes.outputs.changed_projects }}' | jq -r '.[]?') | |
| start_index=$(( ${{ matrix.index }} * ${{ env.MIN_PROJECTS_PER_JOB }} )) | |
| end_index=$(( start_index + ${{ env.MIN_PROJECTS_PER_JOB }} )) | |
| end_index=$(( end_index > ${{ needs.changes.outputs.total_projects }} ? ${{ needs.changes.outputs.total_projects }} : end_index )) | |
| echo "Projects to build and test in this job" | |
| for i in $(seq $start_index $(( end_index - 1 ))); do | |
| echo "${all_projects[$i]}" | |
| done | |
| failed=false | |
| for i in $(seq $start_index $(( end_index - 1 ))); do | |
| echo "::group::Building and testing ${all_projects[$i]}" | |
| if ! build_and_test "${all_projects[$i]}" "$solana_version"; then | |
| failed=true | |
| fi | |
| echo "::endgroup::" | |
| done | |
| return $([ "$failed" = true ] && echo 1 || echo 0) | |
| } | |
| EOF | |
| chmod +x build_and_test.sh | |
| - name: Setup Solana Stable | |
| uses: heyAyushh/setup-solana@v5.9 | |
| with: | |
| # setup-anchor resolves tags like stable by querying GitHub API for latest release which can fail with 429 errors | |
| solana-cli-version: 3.1.14 | |
| - name: Install Quasar CLI | |
| # Pinned to quasar rev 3d6fb0d8 (the HEAD this migration was written | |
| # against, immediately after PRs #195 + #196). The next merged PR | |
| # (#198 "idl-redesign-clean", rev 096c8f7c) regressed `quasar build` | |
| # for flat-layout projects: the new IDL flow chdirs to | |
| # `crate_path.parent()` which evaluates to an empty PathBuf when | |
| # the program crate is at the project root (src/lib.rs in `.`), | |
| # causing posix_spawn child chdir("") to fail with ENOENT before | |
| # any compilation begins. Symptom in CI is a bare "Anyhow error". | |
| # Unpin once upstream lands a fix that handles the flat layout. | |
| run: cargo install --git https://github.com/blueshift-gg/quasar --rev 3d6fb0d8 quasar-cli --locked | |
| - name: Build and Test with Stable | |
| run: | | |
| source build_and_test.sh | |
| solana -V | |
| rustc -V | |
| quasar --version || true | |
| process_projects "stable" | |
| - name: Set failed projects output | |
| id: set-failed | |
| if: failure() | |
| run: | | |
| if [ -f "$GITHUB_WORKSPACE/failed_projects.txt" ]; then | |
| failed_projects=$(cat $GITHUB_WORKSPACE/failed_projects.txt | jq -R -s -c 'split("\n")[:-1]') | |
| echo "failed_projects=$failed_projects" >> $GITHUB_OUTPUT | |
| else | |
| echo "failed_projects=[]" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Show sccache stats | |
| if: always() | |
| run: sccache --show-stats | |
| summary: | |
| needs: [changes, build-and-test] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Create job summary | |
| run: | | |
| echo "## Quasar Workflow Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "- Total projects: ${{ needs.changes.outputs.total_projects }}" >> $GITHUB_STEP_SUMMARY | |
| # List all processed projects | |
| echo "<details>" >> $GITHUB_STEP_SUMMARY | |
| echo "<summary>Projects processed (click to expand)</summary>" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo '${{ needs.changes.outputs.changed_projects }}' | jq -r '.[]' | while read project; do | |
| echo "- $project" >> $GITHUB_STEP_SUMMARY | |
| done | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "</details>" >> $GITHUB_STEP_SUMMARY | |
| # Report build and test results | |
| if [[ "${{ needs.build-and-test.result }}" == "failure" ]]; then | |
| echo "## :x: Build or tests failed" >> $GITHUB_STEP_SUMMARY | |
| echo "<details>" >> $GITHUB_STEP_SUMMARY | |
| echo "<summary>Failed projects (click to expand)</summary>" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| failed_projects='${{ needs.build-and-test.outputs.failed_projects }}' | |
| if [[ -n "$failed_projects" ]]; then | |
| echo "$failed_projects" | jq -r '.[]' | while IFS=: read -r project failure_reason; do | |
| echo "- **$project**" >> $GITHUB_STEP_SUMMARY | |
| echo " - Failure reason: $failure_reason" >> $GITHUB_STEP_SUMMARY | |
| done | |
| else | |
| echo "No failed projects reported. This might indicate an unexpected error in the workflow." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "</details>" >> $GITHUB_STEP_SUMMARY | |
| elif [[ "${{ needs.build-and-test.result }}" == "success" ]]; then | |
| echo "## :white_check_mark: All builds and tests passed" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "## :warning: Build and test job was skipped or canceled" >> $GITHUB_STEP_SUMMARY | |
| fi |