name: deploy-contract on: release: types: [published] workflow_dispatch: jobs: deploy-contract: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set our dev keypair as default solana wallet run: | mkdir -p "$HOME/.config/solana" cp deploy/dev_smart_updown-keypair.json "$HOME/.config/solana/id.json" # убедимся что это именно наш ключ ls -l "$HOME/.config/solana/id.json" - name: Setup Rust toolchain + C compiler run: | set -e apt-get update apt-get install -y --no-install-recommends build-essential pkg-config libssl-dev clang podman # пробуем стандартный rustup; при недоступности static.rust-lang.org — качаем через podman-контейнер if ! curl -sSfL --max-time 60 https://sh.rustup.rs -o /tmp/rustup-init.sh 2>/dev/null; then echo "sh.rustup.rs недоступен, качаем rustup-init через контейнер" podman run --rm --network=host -v /tmp:/out \ gitea/runner-images:ubuntu-latest \ sh -c 'curl -sSfL https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init -o /out/rustup-init-binary' 2>&1 | tail -1 echo "x" >> /tmp/rustup-init.sh.tmp 2>/dev/null || true # конвертируем бинарь в то, что rustup принимает cp /tmp/rustup-init-binary /tmp/rustup-init.sh 2>/dev/null || true fi # если это бинарь — запускаем его напрямую chmod +x /tmp/rustup-init.sh 2>/dev/null || true if file /tmp/rustup-init.sh 2>/dev/null | grep -q 'ELF'; then /tmp/rustup-init.sh -y --profile minimal --default-toolchain 1.91.0 else sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain 1.91.0 2>/dev/null || \ /tmp/rustup-init.sh -y --profile minimal --default-toolchain 1.91.0 fi - name: Setup Solana CLI (Agave 4.2.2 — builder умеет SBPFv3, как прод mainnet) run: | set -e SOL_VERSION=v4.2.2 cd /tmp curl -sSfL \ "https://github.com/anza-xyz/agave/releases/download/${SOL_VERSION}/solana-release-x86_64-unknown-linux-gnu.tar.bz2" \ -o solana-release.tar.bz2 tar xjf solana-release.tar.bz2 mkdir -p "$HOME/solana-local" cp solana-release/bin/solana* "$HOME/solana-local/" 2>/dev/null || true cp solana-release/bin/cargo-build-bpf "$HOME/solana-local/" 2>/dev/null || true cp solana-release/bin/cargo-build-sbf "$HOME/solana-local/" 2>/dev/null || true cp solana-release/bin/cargo-test-bpf "$HOME/solana-local/" 2>/dev/null || true cp solana-release/bin/cargo-test-sbf "$HOME/solana-local/" 2>/dev/null || true # sbf-sdk и прочие каталоги (deps, perf-libs, sdk) — рекурсивно for d in sdk deps perf-libs; do [ -d "solana-release/bin/$d" ] && cp -r "solana-release/bin/$d" "$HOME/solana-local/" done echo "### предустановка SBF platform-tools (LLVM) с anza-xyz:" cd "$HOME/solana-local/sdk/sbf" export PATH="$HOME/.cargo/bin:$PATH" ls dependencies/platform-tools/llvm/bin/clang 2>/dev/null || bash scripts/install.sh || true ls dependencies/platform-tools/llvm/bin/ 2>/dev/null | grep -iE 'clang|objcopy' | head -6 # линкуем solana toolchain (на случай если install.sh его не сделал) . "$HOME/.cargo/env" 2>/dev/null || true if [ -d "$HOME/solana-local/sdk/sbf/dependencies/platform-tools/rust" ]; then rustup toolchain link solana "$HOME/solana-local/sdk/sbf/dependencies/platform-tools/rust" 2>/dev/null || true fi echo "### sbf-sdk на месте:" ls "$HOME/solana-local/sdk/sbf/" 2>&1 | head -5 echo "$HOME/solana-local" >> "$GITHUB_PATH" echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" export PATH="$HOME/solana-local:$PATH" solana --version - name: Setup Anchor CLI (anchor-next) run: | . "$HOME/.cargo/env" mkdir -p "$HOME/.cargo" printf '[net]\ngit-fetch-with-cli = true\n' > "$HOME/.cargo/config.toml" # ставим сначала через git CLI (обход libgit2-проблем с github auth), иначе --git if ! cargo install --force --git https://github.com/otter-sec/anchor.git \ --branch anchor-next anchor-cli --locked 2>/dev/null; then echo "cargo --git не сработал, собираем через git clone + --path" cd /tmp rm -rf anchor-src && git clone --depth 1 --branch anchor-next \ https://github.com/otter-sec/anchor.git anchor-src cargo install --force --path /tmp/anchor-src/cli --locked \ --root "$HOME/.cargo" --bin anchor fi echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" export PATH="$HOME/.cargo/bin:$PATH" anchor --version # ------ общие: build + test ------ - name: Build program working-directory: program run: | export PATH="$HOME/solana-local:$HOME/.cargo/bin:$PATH" echo "### HOME=$HOME" mkdir -p "$HOME/.config/solana" cp ../deploy/dev_smart_updown-keypair.json "$HOME/.config/solana/id.json" echo "### размещаем наш keypair в .anchor (для Program ID 9ALs)" mkdir -p .anchor cp ../deploy/dev_smart_updown-keypair.json .anchor/smart-updown-keypair.json cp ../deploy/dev_smart_updown-keypair.json .anchor/smart_updown-keypair.json 2>/dev/null || true cp ../deploy/dev_smart_updown-keypair.json .anchor/9ALsnxXNzDBv3mokngCHbruRTWUZiWR7pf7vswS1fCpf-keypair.json 2>/dev/null || true ls -la .anchor/ echo "### cargo-build-sbf версия и arch:" "$HOME/solana-local/cargo-build-sbf" --version 2>&1 | head -2 "$HOME/solana-local/cargo-build-sbf" --help 2>&1 | grep -iE 'arch|elf|sbpf|target' | head -10 echo "### (конец дигнocтика arch)" echo "### построение:" anchor build --ignore-keys - name: Test program working-directory: program run: | export PATH="$HOME/solana-local:$HOME/.cargo/bin:$PATH" anchor test # ------ deploy: ТОЛЬКО в нашу сеть (постоянный Solana-валидатор solana-net) ------ - name: Deploy contract (только наша сеть solana-net) working-directory: program run: | export PATH="$HOME/solana-local:$HOME/.cargo/bin:$PATH" RPC=http://192.168.76.181:8899 echo ">>> Деплой в НАШУ сеть solana-net (RPC $RPC)" echo "### sbpf-версия артефакта:" SO=target/deploy/smart_updown.so ls -la "$SO" readelf -S "$SO" 2>/dev/null | grep -iE "sbpf|note|\.dynamic" | head readelf -p .dynamic "$SO" 2>/dev/null | grep -iE "SB|VERSION|tags" | head # TAGS/sbpf версия в строке .dynstr / env strings "$SO" 2>/dev/null | grep -iE "sbpf|sbf" | head echo "### sbpf-версия (end)" # проверка, что наша сеть жива for i in $(seq 1 20); do curl -s $RPC -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}' 2>/dev/null | grep -q '"ok"' && break echo "ждём сеть ($i)"; sleep 3 done # add SOL нашему ключу через свой faucet (9900) — в нашей сети банкир = дефолт mkdir -p "$HOME/.config/solana" cp ../deploy/dev_smart_updown-keypair.json "$HOME/.config/solana/id.json" solana airdrop 100 9ALsnxXNzDBv3mokngCHbruRTWUZiWR7pf7vswS1fCpf \ --url $RPC || true solana balance 9ALsnxXNzDBv3mokngCHbruRTWUZiWR7pf7vswS1fCpf --url $RPC solana config set --url $RPC # Anchor НЕ принимает URL в --provider.cluster; указываем сеть через [provider] в Anchor.toml sed -i "s#cluster = \".*\"#cluster = \"$RPC\"#" Anchor.toml anchor deploy --provider.cluster "$RPC" \ --provider.wallet "$HOME/.config/solana/id.json" echo ">>> ГОТОВО: контракт задеплоен в нашу сеть $RPC"