diff --git a/.github/actions/setup-anchor/action.yml b/.github/actions/setup-anchor/action.yml deleted file mode 100644 index e2225e39e..000000000 --- a/.github/actions/setup-anchor/action.yml +++ /dev/null @@ -1,142 +0,0 @@ -# Vendored from https://github.com/heyAyushh/setup-anchor @v4.999 (MIT, see LICENSE) -name: 'Setup Anchor' -description: 'Install Anchor, Solana CLI tools, and Node.js.' -branding: - icon: anchor - color: blue -inputs: - node-version: - description: 'Version of node.js to use' - required: false - default: 'lts/*' - solana-cli-version: - description: 'Version of Solana CLI to use' - required: false - default: 'stable' - anchor-version: - description: 'Version of Anchor to use' - required: false - default: '0.31.1' - use-avm: - description: 'Use Anchor Version Manager (AVM) to install Anchor' - required: false - default: "true" - -runs: - using: 'composite' - steps: - - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - cache: pnpm - cache-dependency-path: '**/pnpm-lock.yaml' - - - name: Output Node Version - id: node_v - shell: bash - run: | - echo "node_v=$(node -v)" >> $GITHUB_OUTPUT - echo "Using Node version: $(node -v)" - - - name: Setup Solana - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 - with: - solana-cli-version: ${{ inputs.solana-cli-version }} - - - name: Verify Solana installation - shell: bash - run: | - if ! command -v solana &> /dev/null; then - echo "ERROR: Solana CLI installation failed" - exit 1 - fi - echo "Solana CLI version: $(solana --version)" - solana_version=$(echo $(solana --version) | awk '{print $2}') - echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV - - - name: Generate cache key - id: cache-key - shell: bash - run: | - echo "key=${{ runner.os }}-anchor-v${{ inputs.anchor-version }}-solana-v$SOLANA_VERSION" >> $GITHUB_OUTPUT - - - name: Cache Anchor and Cargo - id: cache-anchor - uses: actions/cache@v4 - with: - path: | - ~/.cargo/bin/avm - ~/.cargo/bin/anchor - ~/.avm - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - key: ${{ steps.cache-key.outputs.key }} - - - name: Check for existing anchor installation - id: check-anchor - shell: bash - run: | - if command -v anchor &> /dev/null; then - installed_version=$(anchor --version | awk '/^anchor-cli / {v=$2} END {print v}') - echo "anchor_exists=true" >> $GITHUB_OUTPUT - echo "installed_version=$installed_version" >> $GITHUB_OUTPUT - echo "Found existing Anchor installation: $installed_version" - else - echo "anchor_exists=false" >> $GITHUB_OUTPUT - echo "No existing Anchor installation found" - fi - - - name: Clean existing Anchor installation if version mismatch - if: steps.check-anchor.outputs.anchor_exists == 'true' && steps.check-anchor.outputs.installed_version != inputs.anchor-version - shell: bash - run: | - echo "Removing existing Anchor version to install requested version" - rm -rf ~/.cargo/bin/anchor - rm -rf ~/.avm - - - name: Install Anchor with AVM - if: (steps.cache-anchor.outputs.cache-hit != 'true') || (steps.check-anchor.outputs.anchor_exists != 'true') - shell: bash - run: | - echo "Installing Anchor v${{ inputs.anchor-version }} via AVM..." - set -e - if ! command -v avm &> /dev/null; then - echo "Installing AVM..." - cargo install --git https://github.com/coral-xyz/anchor avm --force - fi - avm --version - avm install ${{ inputs.anchor-version }} - avm use ${{ inputs.anchor-version }} - - if ! command -v anchor &> /dev/null; then - echo "ERROR: AVM installation failed, falling back to direct cargo install" - cargo install --git https://github.com/coral-xyz/anchor --tag v${{ inputs.anchor-version }} anchor-cli --force - if ! command -v anchor &> /dev/null; then - echo "ERROR: Cargo installation failed." - exit 1 - fi - else - echo "AVM installation successful: $(anchor --version)" - exit 0 - fi - - - name: Verify Anchor and Rust installation - shell: bash - run: | - if ! command -v anchor &> /dev/null; then - echo "ERROR: Anchor installation verification failed" - exit 1 - fi - - anchor_version=$(anchor --version) - echo "Anchor installed successfully: $anchor_version" - - # Verify version matches requested version - if [[ ! "$anchor_version" == *"${{ inputs.anchor-version }}"* ]]; then - echo "WARNING: Installed version ($anchor_version) may not match requested version (${{ inputs.anchor-version }})" - fi - - rust_version=$(rustc --version | awk '{print $2}') - echo "Rust version: $rust_version" diff --git a/.github/actions/setup-anchor/LICENSE b/.github/actions/setup/LICENSE similarity index 100% rename from .github/actions/setup-anchor/LICENSE rename to .github/actions/setup/LICENSE diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 000000000..04ed96f44 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,295 @@ +# Single setup action for every build workflow: declare what to install and +# which version, get caching for free. Solana installs straight from +# release.anza.xyz ("stable"/"beta" resolve through scripts/channel-info.sh, +# vendored from heyAyushh/setup-solana v5.9, MIT — see LICENSE; the scripts +# themselves come from anza-xyz/agave, Apache-2.0). Anchor/AVM logic folded in +# from the previously vendored setup-anchor action. +name: 'Setup CI Environment' +description: 'Shared setup for pnpm/Node, Solana, Anchor, just, sbpf, and cargo caching' + +inputs: + install-pnpm: + description: 'Install pnpm and Node.js with a pnpm store cache' + required: false + default: 'true' + node-version: + description: 'Node.js version (ignored when node-version-file is set)' + required: false + default: 'lts/*' + node-version-file: + description: 'Path to a version file (e.g. .nvmrc); overrides node-version' + required: false + default: '' + pnpm-lock-glob: + description: 'Lockfile glob that keys the pnpm store cache' + required: false + default: '**/pnpm-lock.yaml' + install-solana: + description: 'Install the Solana CLI' + required: false + default: 'true' + solana-version: + description: "Solana version: exact (e.g. '4.0.3') or channel ('stable' | 'beta')" + required: false + default: 'stable' + install-anchor: + description: 'Install Anchor via AVM' + required: false + default: 'false' + anchor-version: + description: 'Anchor version to install' + required: false + default: '1.0.2' + install-just: + description: 'Install just' + required: false + default: 'false' + install-sbpf: + description: 'Install the sbpf assembler' + required: false + default: 'false' + sbpf-rev: + description: >- + blueshift-gg/sbpf git rev. Pinned to v0.1.9: the tip moved to v0.2.2, + which emits an sBPF binary the runtime loader rejects at execution + ("Program is not deployed"). Keep in sync with the ASM workflow's pinned + Solana version. + required: false + default: '0223df0e7ba622d4956b4ecf3cf2397f6945b76b' + cargo-cache: + description: 'Cache the cargo registry (and optionally targets) via rust-cache' + required: false + default: 'true' + cargo-cache-key: + description: 'Shared key for the cargo cache' + required: false + default: 'cargo-registry' + cargo-cache-workspaces: + description: 'Workspaces argument for rust-cache' + required: false + default: '.' + cargo-cache-targets: + description: 'Also cache target dirs (keep off for SBF builds: too large)' + required: false + default: 'false' + +runs: + using: 'composite' + steps: + - name: Install pnpm + if: inputs.install-pnpm == 'true' + uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 + + - name: Setup Node.js + if: inputs.install-pnpm == 'true' && inputs.node-version-file == '' + uses: actions/setup-node@v5 + with: + node-version: ${{ inputs.node-version }} + check-latest: true + cache: pnpm + cache-dependency-path: ${{ inputs.pnpm-lock-glob }} + + - name: Setup Node.js (version file) + if: inputs.install-pnpm == 'true' && inputs.node-version-file != '' + uses: actions/setup-node@v5 + with: + node-version-file: ${{ inputs.node-version-file }} + check-latest: true + cache: pnpm + cache-dependency-path: ${{ inputs.pnpm-lock-glob }} + + - name: Cargo cache + if: inputs.cargo-cache == 'true' + uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: ${{ inputs.cargo-cache-workspaces }} + shared-key: ${{ inputs.cargo-cache-key }} + cache-targets: ${{ inputs.cargo-cache-targets }} + + - name: Resolve Solana version + if: inputs.install-solana == 'true' + id: solana-release + shell: bash + run: | + version='${{ inputs.solana-version }}' + if [[ "$version" =~ ^[0-9] ]]; then + resolved="$version" + # Exact pins get a stable cache key + echo "cache_key=solana-${{ runner.os }}-v$resolved" >> $GITHUB_OUTPUT + else + chmod +x "${{ github.action_path }}/scripts/channel-info.sh" + read -r BETA_CHANNEL_LATEST_TAG STABLE_CHANNEL_LATEST_TAG <<< "$("${{ github.action_path }}/scripts/channel-info.sh")" + case "$version" in + stable) tag="$STABLE_CHANNEL_LATEST_TAG" ;; + beta) tag="$BETA_CHANNEL_LATEST_TAG" ;; + *) echo "::error::Unsupported solana-version '$version' (use an exact version, 'stable', or 'beta')"; exit 1 ;; + esac + if [[ -z "$tag" || "$tag" == "none" ]]; then + echo "::error::No release tag for Solana channel '$version'" + exit 1 + fi + resolved="${tag#v}" + # Channels move: include year+week so the cache refreshes weekly + echo "cache_key=solana-${{ runner.os }}-v$resolved-$(date +%Y%V)" >> $GITHUB_OUTPUT + fi + echo "Using Solana CLI version $resolved" + echo "install_version=v$resolved" >> $GITHUB_OUTPUT + echo "version=$resolved" >> $GITHUB_OUTPUT + + # Clean existing installations to prevent version conflicts (a job may + # call this action twice, e.g. stable then beta) + - name: Clean existing Solana installation + if: inputs.install-solana == 'true' + shell: bash + run: | + rm -rf ~/.cache/solana + rm -rf ~/.local/share/solana + rm -rf ~/.solana + rm -rf ~/.config/solana + rm -rf ~/.cargo/bin/cargo-build-sbf + rm -rf ~/.cargo/bin/cargo-test-sbf + + - name: Cache Solana environment + if: inputs.install-solana == 'true' + id: cache-solana + uses: actions/cache@v4 + with: + path: | + ~/.cache/solana/ + ~/.local/share/solana/ + ~/.solana/ + ~/.config/solana/ + ~/.cargo/bin/cargo-build-sbf + ~/.cargo/bin/cargo-test-sbf + key: ${{ steps.solana-release.outputs.cache_key }} + + - name: Install Solana CLI tools + if: inputs.install-solana == 'true' && steps.cache-solana.outputs.cache-hit != 'true' + shell: bash + run: sh -c "$(curl -sSfL https://release.anza.xyz/${{ steps.solana-release.outputs.install_version }}/install)" + + - name: Verify Solana version + if: inputs.install-solana == 'true' + shell: bash + run: | + echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH + export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" + + INSTALLED_VERSION=$(solana --version | grep -oP 'solana-cli \K[0-9]+\.[0-9]+\.[0-9]+') + EXPECTED_VERSION="${{ steps.solana-release.outputs.version }}" + + echo "Installed version: $INSTALLED_VERSION" + echo "Expected version: $EXPECTED_VERSION" + + if [[ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]]; then + echo "Version mismatch! Expected $EXPECTED_VERSION but got $INSTALLED_VERSION" + rm -rf ~/.cache/solana + rm -rf ~/.local/share/solana + sh -c "$(curl -sSfL https://release.anza.xyz/v$EXPECTED_VERSION/install)" + fi + + echo "Final Solana version:" + solana --version + cargo-build-sbf --version + + - name: Generate Anchor cache key + if: inputs.install-anchor == 'true' + id: anchor-cache-key + shell: bash + run: echo "key=${{ runner.os }}-anchor-v${{ inputs.anchor-version }}-solana-v${{ steps.solana-release.outputs.version }}" >> $GITHUB_OUTPUT + + - name: Cache Anchor and Cargo binaries + if: inputs.install-anchor == 'true' + id: cache-anchor + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/avm + ~/.cargo/bin/anchor + ~/.avm + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + key: ${{ steps.anchor-cache-key.outputs.key }} + + - name: Check for existing Anchor installation + if: inputs.install-anchor == 'true' + id: check-anchor + shell: bash + run: | + if command -v anchor &> /dev/null; then + installed_version=$(anchor --version | awk '/^anchor-cli / {v=$2} END {print v}') + echo "anchor_exists=true" >> $GITHUB_OUTPUT + echo "installed_version=$installed_version" >> $GITHUB_OUTPUT + echo "Found existing Anchor installation: $installed_version" + else + echo "anchor_exists=false" >> $GITHUB_OUTPUT + echo "No existing Anchor installation found" + fi + + - name: Clean existing Anchor installation if version mismatch + if: inputs.install-anchor == 'true' && steps.check-anchor.outputs.anchor_exists == 'true' && steps.check-anchor.outputs.installed_version != inputs.anchor-version + shell: bash + run: | + echo "Removing existing Anchor version to install requested version" + rm -rf ~/.cargo/bin/anchor + rm -rf ~/.avm + + - name: Install Anchor with AVM + if: inputs.install-anchor == 'true' && ((steps.cache-anchor.outputs.cache-hit != 'true') || (steps.check-anchor.outputs.anchor_exists != 'true')) + shell: bash + run: | + echo "Installing Anchor v${{ inputs.anchor-version }} via AVM..." + set -e + if ! command -v avm &> /dev/null; then + echo "Installing AVM..." + cargo install --git https://github.com/coral-xyz/anchor avm --force + fi + avm --version + avm install ${{ inputs.anchor-version }} + avm use ${{ inputs.anchor-version }} + + if ! command -v anchor &> /dev/null; then + echo "ERROR: AVM installation failed, falling back to direct cargo install" + cargo install --git https://github.com/coral-xyz/anchor --tag v${{ inputs.anchor-version }} anchor-cli --force + if ! command -v anchor &> /dev/null; then + echo "ERROR: Cargo installation failed." + exit 1 + fi + else + echo "AVM installation successful: $(anchor --version)" + fi + + - name: Verify Anchor installation + if: inputs.install-anchor == 'true' + shell: bash + run: | + if ! command -v anchor &> /dev/null; then + echo "ERROR: Anchor installation verification failed" + exit 1 + fi + + anchor_version=$(anchor --version) + echo "Anchor installed successfully: $anchor_version" + + if [[ ! "$anchor_version" == *"${{ inputs.anchor-version }}"* ]]; then + echo "WARNING: Installed version ($anchor_version) may not match requested version (${{ inputs.anchor-version }})" + fi + + - name: Install just + if: inputs.install-just == 'true' + uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 + + - name: Cache sbpf assembler + if: inputs.install-sbpf == 'true' + id: cache-sbpf + uses: actions/cache@v4 + with: + path: ~/.cargo/bin/sbpf + key: ${{ runner.os }}-sbpf-${{ inputs.sbpf-rev }} + + - name: Install sbpf assembler + if: inputs.install-sbpf == 'true' && steps.cache-sbpf.outputs.cache-hit != 'true' + shell: bash + run: cargo install --git https://github.com/blueshift-gg/sbpf.git --rev ${{ inputs.sbpf-rev }} diff --git a/.github/actions/setup/scripts/channel-info.sh b/.github/actions/setup/scripts/channel-info.sh new file mode 100755 index 000000000..bb512d52b --- /dev/null +++ b/.github/actions/setup/scripts/channel-info.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Code: https://github.com/anza-xyz/agave/blob/master/ci/channel-info.sh +# Source: Agave project (https://github.com/anza-xyz/agave) +# Copyright (c) 2023 Anza XYZ +# License: Apache-2.0 license +# +# Computes the current branch names of the edge, beta and stable +# channels, as well as the latest tagged release for beta and stable. +# +# stdout of this script may be eval-ed +# + +here="$(dirname "$0")" + +# shellcheck source=scripts/semver.sh +source "$here"/semver.sh + +remote=https://github.com/anza-xyz/agave.git + +# Fetch all vX.Y.Z tags +# +# NOTE: pre-release tags are explicitly ignored +# +# shellcheck disable=SC2207 +tags=( \ + $(git ls-remote --tags $remote \ + | cut -c52- \ + | grep '^v[[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]*.[[:digit:]][[:digit:]]*$' \ + | cut -c2- \ + ) \ +) + +# Fetch all the vX.Y branches +# +# shellcheck disable=SC2207 +heads=( \ + $(git ls-remote --heads $remote \ + | cut -c53- \ + | grep '^v[[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]*$' \ + | cut -c2- \ + ) \ +) + +# Figure the beta channel by looking for the largest vX.Y branch +beta= +for head in "${heads[@]}"; do + if [[ -n $beta ]]; then + if semverLT "$head.0" "$beta.0"; then + continue + fi + fi + beta=$head +done + +# Figure the stable channel by looking for the second largest vX.Y branch +stable= +for head in "${heads[@]}"; do + if [[ $head = "$beta" ]]; then + continue + fi + if [[ -n $stable ]]; then + if semverLT "$head.0" "$stable.0"; then + continue + fi + fi + stable=$head +done + +for tag in "${tags[@]}"; do + if [[ -n $beta && $tag = $beta* ]]; then + if [[ -n $beta_tag ]]; then + if semverLT "$tag" "$beta_tag"; then + continue + fi + fi + beta_tag=$tag + fi + + if [[ -n $stable && $tag = $stable* ]]; then + if [[ -n $stable_tag ]]; then + if semverLT "$tag" "$stable_tag"; then + continue + fi + fi + stable_tag=$tag + fi +done + +EDGE_CHANNEL=master +BETA_CHANNEL=${beta:+v$beta} +STABLE_CHANNEL=${stable:+v$stable} +BETA_CHANNEL_LATEST_TAG=${beta_tag:+v$beta_tag} +STABLE_CHANNEL_LATEST_TAG=${stable_tag:+v$stable_tag} + + +if [[ -n $CI_BASE_BRANCH ]]; then + BRANCH="$CI_BASE_BRANCH" +elif [[ -n $CI_BRANCH ]]; then + BRANCH="$CI_BRANCH" +fi + +if [[ -z "$CHANNEL" ]]; then + if [[ $BRANCH = "$STABLE_CHANNEL" ]]; then + CHANNEL=stable + elif [[ $BRANCH = "$EDGE_CHANNEL" ]]; then + CHANNEL=edge + elif [[ $BRANCH = "$BETA_CHANNEL" ]]; then + CHANNEL=beta + fi +fi + +if [[ $CHANNEL = beta ]]; then + CHANNEL_LATEST_TAG="$BETA_CHANNEL_LATEST_TAG" +elif [[ $CHANNEL = stable ]]; then + CHANNEL_LATEST_TAG="$STABLE_CHANNEL_LATEST_TAG" +fi + +# "none" placeholders keep the two fields positional when a channel has no +# tag (an empty first field would shift stable into the beta slot on read) +echo "${BETA_CHANNEL_LATEST_TAG:-none} ${STABLE_CHANNEL_LATEST_TAG:-none}" + +exit 0 diff --git a/.github/actions/setup/scripts/semver.sh b/.github/actions/setup/scripts/semver.sh new file mode 100755 index 000000000..c57d1aabe --- /dev/null +++ b/.github/actions/setup/scripts/semver.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env sh + +# Code: https://github.com/anza-xyz/agave/blob/master/ci/semver_bash/semver.sh +# Source: Agave project (https://github.com/anza-xyz/agave) +# Copyright (c) 2023 Anza XYZ +# License: Apache-2.0 license + +function semverParseInto() { + local RE='[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)' + #MAJOR + eval $2=`echo $1 | sed -e "s#$RE#\1#"` + #MINOR + eval $3=`echo $1 | sed -e "s#$RE#\2#"` + #MINOR + eval $4=`echo $1 | sed -e "s#$RE#\3#"` + #SPECIAL + eval $5=`echo $1 | sed -e "s#$RE#\4#"` +} + +function semverEQ() { + local MAJOR_A=0 + local MINOR_A=0 + local PATCH_A=0 + local SPECIAL_A=0 + + local MAJOR_B=0 + local MINOR_B=0 + local PATCH_B=0 + local SPECIAL_B=0 + + semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A + semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B + + if [ $MAJOR_A -ne $MAJOR_B ]; then + return 1 + fi + + if [ $MINOR_A -ne $MINOR_B ]; then + return 1 + fi + + if [ $PATCH_A -ne $PATCH_B ]; then + return 1 + fi + + if [[ "_$SPECIAL_A" != "_$SPECIAL_B" ]]; then + return 1 + fi + + + return 0 + +} + +function semverLT() { + local MAJOR_A=0 + local MINOR_A=0 + local PATCH_A=0 + local SPECIAL_A=0 + + local MAJOR_B=0 + local MINOR_B=0 + local PATCH_B=0 + local SPECIAL_B=0 + + semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A + semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B + + if [ $MAJOR_A -lt $MAJOR_B ]; then + return 0 + fi + + if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -lt $MINOR_B ]]; then + return 0 + fi + + if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -le $MINOR_B && $PATCH_A -lt $PATCH_B ]]; then + return 0 + fi + + if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then + return 1 + fi + if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" != "_" ]] ; then + return 1 + fi + if [[ "_$SPECIAL_A" != "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then + return 0 + fi + + if [[ "_$SPECIAL_A" < "_$SPECIAL_B" ]]; then + return 0 + fi + + return 1 + +} + +function semverGT() { + semverEQ $1 $2 + local EQ=$? + + semverLT $1 $2 + local LT=$? + + if [ $EQ -ne 0 ] && [ $LT -ne 0 ]; then + return 0 + else + return 1 + fi +} + +if [ "___semver.sh" == "___`basename $0`" ]; then + +MAJOR=0 +MINOR=0 +PATCH=0 +SPECIAL="" + +semverParseInto $1 MAJOR MINOR PATCH SPECIAL +echo "$1 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL" + +semverParseInto $2 MAJOR MINOR PATCH SPECIAL +echo "$2 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL" + +semverEQ $1 $2 +echo "$1 == $2 -> $?." + +semverLT $1 $2 +echo "$1 < $2 -> $?." + +semverGT $1 $2 +echo "$1 > $2 -> $?." + +fi diff --git a/.github/workflows/anchor.yml b/.github/workflows/anchor.yml index 390a33f64..419008bac 100644 --- a/.github/workflows/anchor.yml +++ b/.github/workflows/anchor.yml @@ -123,15 +123,10 @@ jobs: failed_projects: ${{ steps.set-failed.outputs.failed_projects }} steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - uses: ./.github/actions/setup with: - shared-key: cargo-registry - cache-targets: false - - uses: ./.github/actions/setup-anchor - with: - anchor-version: 1.0.2 - solana-cli-version: stable + install-anchor: 'true' + anchor-version: '1.0.2' - name: Display Versions run: | solana -V diff --git a/.github/workflows/just.yml b/.github/workflows/just.yml index eac82e775..0887fedec 100644 --- a/.github/workflows/just.yml +++ b/.github/workflows/just.yml @@ -95,24 +95,14 @@ jobs: name: ${{ matrix.project }} steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - - name: Use Node.js - uses: actions/setup-node@v5 + - uses: ./.github/actions/setup with: node-version-file: ${{ matrix.project }}/.nvmrc - check-latest: true - cache: pnpm - cache-dependency-path: ${{ matrix.project }}/pnpm-lock.yaml - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - workspaces: ${{ matrix.project }} - shared-key: ${{ matrix.project }} - - name: Install just - uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 - - name: Setup Solana - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 - with: - solana-cli-version: stable + pnpm-lock-glob: ${{ matrix.project }}/pnpm-lock.yaml + install-just: 'true' + cargo-cache-workspaces: ${{ matrix.project }} + cargo-cache-key: ${{ matrix.project }} + cargo-cache-targets: 'true' - name: Build and test working-directory: ${{ matrix.project }} run: | diff --git a/.github/workflows/solana-asm.yml b/.github/workflows/solana-asm.yml index 1249ab237..bb075209a 100644 --- a/.github/workflows/solana-asm.yml +++ b/.github/workflows/solana-asm.yml @@ -122,33 +122,14 @@ jobs: failed_projects: ${{ steps.set-failed.outputs.failed_projects }} steps: - uses: actions/checkout@v7 - # pnpm/action-setup installs the packageManager version pinned in - # package.json (unpinned latest pnpm fails CI with ERR_PNPM_IGNORED_BUILDS) - - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - - name: Use Node.js - uses: actions/setup-node@v4 + # Solana pinned to 4.0.3, the last version the ASM examples passed on + # (paired with the sbpf rev pinned in the setup action). Floating + # "stable" moved to 4.1.1 in the same window the toolchain broke. The + # beta leg below stays on the moving channel on purpose. + - uses: ./.github/actions/setup with: - node-version: "lts/*" - check-latest: true - cache: pnpm - cache-dependency-path: '**/pnpm-lock.yaml' - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - shared-key: cargo-registry - cache-targets: false - - name: Cache sbpf assembler - id: cache-sbpf - uses: actions/cache@v4 - with: - path: ~/.cargo/bin/sbpf - key: ${{ runner.os }}-sbpf-0223df0e7ba622d4956b4ecf3cf2397f6945b76b - # Pinned to v0.1.9 (0223df0e): the unpinned tip moved to v0.2.2, which - # emits an sBPF binary the runtime loader rejects at execution - # ("Program is not deployed"), breaking every ASM example. Keep in sync - # with the pinned Solana version below. - - name: Install sbpf assembler - if: steps.cache-sbpf.outputs.cache-hit != 'true' - run: cargo install --git https://github.com/blueshift-gg/sbpf.git --rev 0223df0e7ba622d4956b4ecf3cf2397f6945b76b + solana-version: '4.0.3' + install-sbpf: 'true' - name: Setup build environment id: setup run: | @@ -230,14 +211,6 @@ jobs: # Make the script executable chmod +x build_and_test.sh - - name: Setup Solana Stable - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 - with: - # Pinned to 4.0.3, the last version the ASM examples passed on (paired - # with sbpf v0.1.9 above). Floating "stable" moved to 4.1.1 in the same - # window the toolchain broke. The beta leg below stays unpinned on - # purpose (it is continue-on-error and tracks the moving channel). - solana-cli-version: 4.0.3 - name: Build and Test with Stable run: | source build_and_test.sh @@ -245,16 +218,18 @@ jobs: rustc -V process_projects "stable" # Beta runs only on the nightly schedule and never blocks: the beta - # channel may not have a valid release (e.g. v4.0 returns 404 from - # release.anza.xyz — upstream issue with heyAyushh/setup-solana), and - # beta setup clears the stable install first. + # channel may not have a tagged release, and beta setup clears the + # stable install first. - name: Setup Solana Beta id: setup-beta if: github.event_name == 'schedule' continue-on-error: true - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 + uses: ./.github/actions/setup with: - solana-cli-version: beta + solana-version: beta + install-pnpm: 'false' + cargo-cache: 'false' + install-sbpf: 'false' - name: Build and Test with Beta id: test-beta if: github.event_name == 'schedule' && steps.setup-beta.outcome == 'success' diff --git a/.github/workflows/solana-native.yml b/.github/workflows/solana-native.yml index a3bad5b22..df10def3d 100644 --- a/.github/workflows/solana-native.yml +++ b/.github/workflows/solana-native.yml @@ -124,18 +124,7 @@ jobs: failed_projects: ${{ steps.set-failed.outputs.failed_projects }} steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - - name: Use Node.js - uses: actions/setup-node@v5 - with: - node-version: 'lts/*' - check-latest: true - cache: pnpm - cache-dependency-path: '**/pnpm-lock.yaml' - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - shared-key: cargo-registry - cache-targets: false + - uses: ./.github/actions/setup - name: Setup build environment id: setup run: | @@ -226,10 +215,6 @@ jobs: # Make the script executable chmod +x build_and_test.sh - - name: Setup Solana Stable - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 - with: - solana-cli-version: stable - name: Build and Test with Stable run: | source build_and_test.sh @@ -237,16 +222,17 @@ jobs: rustc -V process_projects "stable" # Beta runs only on the nightly schedule and never blocks: the beta - # channel may not have a valid release (e.g. v4.0 returns 404 from - # release.anza.xyz — upstream issue with heyAyushh/setup-solana), and - # beta setup clears the stable install first. + # channel may not have a tagged release, and beta setup clears the + # stable install first. - name: Setup Solana Beta id: setup-beta if: github.event_name == 'schedule' continue-on-error: true - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 + uses: ./.github/actions/setup with: - solana-cli-version: beta + solana-version: beta + install-pnpm: 'false' + cargo-cache: 'false' - name: Build and Test with Beta id: test-beta if: github.event_name == 'schedule' && steps.setup-beta.outcome == 'success' diff --git a/.github/workflows/solana-pinocchio.yml b/.github/workflows/solana-pinocchio.yml index 96a36c5ac..ec9bbf933 100644 --- a/.github/workflows/solana-pinocchio.yml +++ b/.github/workflows/solana-pinocchio.yml @@ -124,18 +124,7 @@ jobs: failed_projects: ${{ steps.set-failed.outputs.failed_projects }} steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - - name: Use Node.js - uses: actions/setup-node@v5 - with: - node-version: "lts/*" - check-latest: true - cache: pnpm - cache-dependency-path: '**/pnpm-lock.yaml' - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - shared-key: cargo-registry - cache-targets: false + - uses: ./.github/actions/setup - name: Setup build environment id: setup run: | @@ -226,10 +215,6 @@ jobs: # Make the script executable chmod +x build_and_test.sh - - name: Setup Solana Stable - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 - with: - solana-cli-version: stable - name: Build and Test with Stable run: | source build_and_test.sh @@ -237,16 +222,17 @@ jobs: rustc -V process_projects "stable" # Beta runs only on the nightly schedule and never blocks: the beta - # channel may not have a valid release (e.g. v4.0 returns 404 from - # release.anza.xyz — upstream issue with heyAyushh/setup-solana), and - # beta setup clears the stable install first. + # channel may not have a tagged release, and beta setup clears the + # stable install first. - name: Setup Solana Beta id: setup-beta if: github.event_name == 'schedule' continue-on-error: true - uses: heyAyushh/setup-solana@667aa7cbe39ba7d585e752a99fb8918c870d1bac # v5.9 + uses: ./.github/actions/setup with: - solana-cli-version: beta + solana-version: beta + install-pnpm: 'false' + cargo-cache: 'false' - name: Build and Test with Beta id: test-beta if: github.event_name == 'schedule' && steps.setup-beta.outcome == 'success'