feat: add dry-run transaction contract #41
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: Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - '**' | |
| paths: | |
| - Cargo.toml | |
| - .github/workflows/release.yml | |
| - Cargo.lock | |
| permissions: | |
| contents: write | |
| env: | |
| BIN_NAME: chainpilot | |
| HOMEBREW_TAP_REPO: DODOEX/homebrew-chainpilot | |
| AUR_PACKAGE_NAME: chainpilot-bin | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| prepare-release: | |
| name: Prepare Release | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| should_release: ${{ steps.detect.outputs.should_release }} | |
| branch_name: ${{ steps.detect.outputs.branch_name }} | |
| cargo_version: ${{ steps.detect.outputs.cargo_version }} | |
| version: ${{ steps.detect.outputs.version }} | |
| tag: ${{ steps.detect.outputs.tag }} | |
| previous_tag: ${{ steps.detect.outputs.previous_tag }} | |
| prerelease: ${{ steps.detect.outputs.prerelease }} | |
| stable: ${{ steps.detect.outputs.stable }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Validate version and release channel | |
| id: detect | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| branch_name="${GITHUB_REF_NAME}" | |
| if [[ -z "$branch_name" ]]; then | |
| echo "Missing branch name from GitHub ref" >&2 | |
| exit 1 | |
| fi | |
| cargo_version=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1) | |
| if [[ -z "$cargo_version" ]]; then | |
| echo "Failed to read version from Cargo.toml" >&2 | |
| exit 1 | |
| fi | |
| version="$cargo_version" | |
| tag="v$version" | |
| is_main=false | |
| if [[ "$branch_name" == "main" ]]; then | |
| is_main=true | |
| fi | |
| prerelease=false | |
| stable=false | |
| if [[ "$version" == *-* ]]; then | |
| prerelease=true | |
| else | |
| stable=true | |
| fi | |
| if [[ "$is_main" == "true" && "$prerelease" == "true" ]]; then | |
| echo "main branch cannot publish prerelease versions: $version — skipping release" | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| echo "branch_name=$branch_name" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "cargo_version=$cargo_version" >> "$GITHUB_OUTPUT" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT" | |
| echo "stable=$stable" >> "$GITHUB_OUTPUT" | |
| echo "previous_tag=" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [[ "$is_main" != "true" && "$stable" == "true" ]]; then | |
| echo "non-main branch must use prerelease versions with a suffix: $version — skipping release" | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| echo "branch_name=$branch_name" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "cargo_version=$cargo_version" >> "$GITHUB_OUTPUT" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT" | |
| echo "stable=$stable" >> "$GITHUB_OUTPUT" | |
| echo "previous_tag=" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then | |
| echo "Tag $tag already exists" | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| echo "branch_name=$branch_name" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "cargo_version=$cargo_version" >> "$GITHUB_OUTPUT" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT" | |
| echo "stable=$stable" >> "$GITHUB_OUTPUT" | |
| previous_tag=$(git tag --sort=-version:refname | head -n1 || true) | |
| echo "previous_tag=$previous_tag" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "should_release=true" >> "$GITHUB_OUTPUT" | |
| echo "branch_name=$branch_name" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "cargo_version=$cargo_version" >> "$GITHUB_OUTPUT" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT" | |
| echo "stable=$stable" >> "$GITHUB_OUTPUT" | |
| previous_tag=$(git tag --sort=-version:refname | head -n1 || true) | |
| echo "previous_tag=$previous_tag" >> "$GITHUB_OUTPUT" | |
| build: | |
| name: Build ${{ matrix.asset_name }} | |
| needs: prepare-release | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-24.04 | |
| target: x86_64-unknown-linux-gnu | |
| asset_name: chainpilot-linux-x86_64 | |
| archive_ext: tar.gz | |
| binary_name: chainpilot | |
| - os: ubuntu-24.04 | |
| target: aarch64-unknown-linux-gnu | |
| asset_name: chainpilot-linux-aarch64 | |
| archive_ext: tar.gz | |
| binary_name: chainpilot | |
| - os: macos-14 | |
| target: x86_64-apple-darwin | |
| asset_name: chainpilot-macos-x86_64 | |
| archive_ext: tar.gz | |
| binary_name: chainpilot | |
| - os: macos-14 | |
| target: aarch64-apple-darwin | |
| asset_name: chainpilot-macos-aarch64 | |
| archive_ext: tar.gz | |
| binary_name: chainpilot | |
| - os: windows-2022 | |
| target: x86_64-pc-windows-msvc | |
| asset_name: chainpilot-windows-x86_64 | |
| archive_ext: zip | |
| binary_name: chainpilot.exe | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.sha }} | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: Install cross-compilation tools (Linux aarch64) | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y gcc-aarch64-linux-gnu | |
| - name: Build release binary | |
| env: | |
| CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc | |
| DODO_API_KEY: ${{ secrets.DODO_API_KEY }} | |
| DODO_PROJECT_ID: ${{ secrets.DODO_PROJECT_ID }} | |
| run: cargo build --release --locked --target ${{ matrix.target }} | |
| - name: Package Unix artifact | |
| if: runner.os != 'Windows' | |
| shell: bash | |
| run: | | |
| mkdir -p dist/${{ matrix.asset_name }} | |
| cp target/${{ matrix.target }}/release/${{ matrix.binary_name }} dist/${{ matrix.asset_name }}/ | |
| tar -C dist -czf dist/${{ matrix.asset_name }}.${{ matrix.archive_ext }} ${{ matrix.asset_name }} | |
| - name: Package Windows artifact | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path "dist/${{ matrix.asset_name }}" | Out-Null | |
| Copy-Item "target/${{ matrix.target }}/release/${{ matrix.binary_name }}" "dist/${{ matrix.asset_name }}/" | |
| Compress-Archive -Path "dist/${{ matrix.asset_name }}" -DestinationPath "dist/${{ matrix.asset_name }}.${{ matrix.archive_ext }}" -Force | |
| - name: Upload packaged artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.asset_name }} | |
| path: dist/${{ matrix.asset_name }}.${{ matrix.archive_ext }} | |
| release: | |
| name: Publish Release | |
| needs: | |
| - prepare-release | |
| - build | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Create and push tag | |
| env: | |
| TAG: ${{ needs.prepare-release.outputs.tag }} | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git tag -a "$TAG" -m "Release $TAG" | |
| git push origin "$TAG" | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| - name: Build release notes | |
| id: changelog | |
| uses: mikepenz/release-changelog-builder-action@v5 | |
| with: | |
| configuration: .github/release-changelog-config.json | |
| mode: COMMIT | |
| toTag: ${{ needs.prepare-release.outputs.tag }} | |
| fromTag: ${{ needs.prepare-release.outputs.previous_tag }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Publish GitHub release assets | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.prepare-release.outputs.tag }} | |
| name: ${{ needs.prepare-release.outputs.tag }} | |
| body: ${{ steps.changelog.outputs.changelog }} | |
| prerelease: ${{ needs.prepare-release.outputs.prerelease }} | |
| files: dist/* | |
| - name: Checkout Homebrew tap repository | |
| if: needs.prepare-release.outputs.stable == 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ env.HOMEBREW_TAP_REPO }} | |
| token: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| path: homebrew-tap | |
| - name: Update Homebrew formula | |
| if: needs.prepare-release.outputs.stable == 'true' | |
| env: | |
| VERSION: ${{ needs.prepare-release.outputs.cargo_version }} | |
| TAG: ${{ needs.prepare-release.outputs.tag }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| linux_x86_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/chainpilot-linux-x86_64.tar.gz" | |
| linux_arm_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/chainpilot-linux-aarch64.tar.gz" | |
| macos_x86_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/chainpilot-macos-x86_64.tar.gz" | |
| macos_arm_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/chainpilot-macos-aarch64.tar.gz" | |
| linux_x86_sha=$(sha256sum dist/chainpilot-linux-x86_64.tar.gz | awk '{print $1}') | |
| linux_arm_sha=$(sha256sum dist/chainpilot-linux-aarch64.tar.gz | awk '{print $1}') | |
| macos_x86_sha=$(sha256sum dist/chainpilot-macos-x86_64.tar.gz | awk '{print $1}') | |
| macos_arm_sha=$(sha256sum dist/chainpilot-macos-aarch64.tar.gz | awk '{print $1}') | |
| mkdir -p homebrew-tap/Formula | |
| cat > homebrew-tap/Formula/chainpilot.rb <<EOF | |
| class Chainpilot < Formula | |
| desc "CLI tool for on-chain DeFi operations on EVM-compatible networks" | |
| homepage "https://github.com/${GITHUB_REPOSITORY}" | |
| version "${VERSION}" | |
| license "MIT" | |
| on_macos do | |
| on_arm do | |
| url "${macos_arm_url}" | |
| sha256 "${macos_arm_sha}" | |
| end | |
| on_intel do | |
| url "${macos_x86_url}" | |
| sha256 "${macos_x86_sha}" | |
| end | |
| end | |
| on_linux do | |
| on_arm do | |
| url "${linux_arm_url}" | |
| sha256 "${linux_arm_sha}" | |
| end | |
| on_intel do | |
| url "${linux_x86_url}" | |
| sha256 "${linux_x86_sha}" | |
| end | |
| end | |
| def install | |
| bin.install "chainpilot" | |
| end | |
| test do | |
| assert_match version.to_s, shell_output("#{bin}/chainpilot --version") | |
| end | |
| end | |
| EOF | |
| - name: Commit and push Homebrew formula update | |
| if: needs.prepare-release.outputs.stable == 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd homebrew-tap | |
| if git diff --quiet; then | |
| echo "No Homebrew formula changes to commit." | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add Formula/chainpilot.rb | |
| git commit -m "chainpilot ${{ needs.prepare-release.outputs.version }}" | |
| git push origin HEAD | |
| - name: Check AUR SSH key | |
| if: needs.prepare-release.outputs.stable == 'true' | |
| id: aur-key | |
| shell: bash | |
| env: | |
| AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }} | |
| run: | | |
| if [[ -n "${AUR_SSH_PRIVATE_KEY}" ]]; then | |
| echo "available=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "available=false" >> "$GITHUB_OUTPUT" | |
| echo "AUR_SSH_PRIVATE_KEY is not configured. Skipping AUR update." | |
| fi | |
| - name: Install SSH key for AUR | |
| if: needs.prepare-release.outputs.stable == 'true' && steps.aur-key.outputs.available == 'true' | |
| shell: bash | |
| env: | |
| AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p ~/.ssh | |
| chmod 700 ~/.ssh | |
| printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/aur | |
| chmod 600 ~/.ssh/aur | |
| ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts | |
| - name: Clone AUR repository | |
| if: needs.prepare-release.outputs.stable == 'true' && steps.aur-key.outputs.available == 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| GIT_SSH_COMMAND='ssh -i ~/.ssh/aur' \ | |
| git clone "ssh://aur@aur.archlinux.org/${AUR_PACKAGE_NAME}.git" aur-repo | |
| - name: Update PKGBUILD and .SRCINFO | |
| if: needs.prepare-release.outputs.stable == 'true' && steps.aur-key.outputs.available == 'true' | |
| shell: bash | |
| env: | |
| TAG: ${{ needs.prepare-release.outputs.tag }} | |
| run: | | |
| set -euo pipefail | |
| version="${TAG#v}" | |
| url="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/chainpilot-linux-x86_64.tar.gz" | |
| sha256="$(curl -fsSL "$url" | sha256sum | awk '{print $1}')" | |
| { | |
| printf '%s\n' '# Maintainer: DODOEX <maintainers@dodoex.io>' | |
| printf '\n' | |
| printf '%s\n' 'pkgname=chainpilot-bin' | |
| printf '%s\n' "pkgver=${version}" | |
| printf '%s\n' 'pkgrel=1' | |
| printf '%s\n' 'pkgdesc="CLI tool for on-chain DeFi operations on EVM-compatible networks"' | |
| printf '%s\n' "url=\"https://github.com/${GITHUB_REPOSITORY}\"" | |
| printf '%s\n' "source=(\"\$pkgname-\$pkgver.tar.gz::https://github.com/${GITHUB_REPOSITORY}/releases/download/v\$pkgver/chainpilot-linux-x86_64.tar.gz\")" | |
| printf '%s\n' 'arch=('\''x86_64'\'')' | |
| printf '%s\n' 'license=('\''MIT'\'')' | |
| printf '%s\n' 'provides=('\''chainpilot'\'')' | |
| printf '%s\n' 'conflicts=('\''chainpilot'\'')' | |
| printf '%s\n' "sha256sums=('${sha256}')" | |
| printf '\n' | |
| printf '%s\n' 'package() {' | |
| printf '%s\n' ' install -Dm755 "$srcdir/chainpilot-linux-x86_64/chainpilot" "$pkgdir/usr/bin/chainpilot"' | |
| printf '%s\n' '}' | |
| } > aur-repo/PKGBUILD | |
| { | |
| printf '%s\n' 'pkgbase = chainpilot-bin' | |
| printf '%s\n' ' pkgdesc = CLI tool for on-chain DeFi operations on EVM-compatible networks' | |
| printf '%s\n' " pkgver = ${version}" | |
| printf '%s\n' ' pkgrel = 1' | |
| printf '%s\n' " url = https://github.com/${GITHUB_REPOSITORY}" | |
| printf '%s\n' ' arch = x86_64' | |
| printf '%s\n' ' license = MIT' | |
| printf '%s\n' ' conflicts = chainpilot' | |
| printf '%s\n' ' provides = chainpilot' | |
| printf '%s\n' " source = chainpilot-bin-${version}.tar.gz::https://github.com/${GITHUB_REPOSITORY}/releases/download/v${version}/chainpilot-linux-x86_64.tar.gz" | |
| printf '%s\n' " sha256sums = ${sha256}" | |
| printf '\n' | |
| printf '%s\n' 'pkgname = chainpilot-bin' | |
| } > aur-repo/.SRCINFO | |
| - name: Commit and push AUR update | |
| if: needs.prepare-release.outputs.stable == 'true' && steps.aur-key.outputs.available == 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd aur-repo | |
| if git diff --quiet; then | |
| echo "No AUR changes to commit." | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add PKGBUILD .SRCINFO | |
| git commit -m "Update to ${AUR_PACKAGE_NAME} ${GITHUB_REF_NAME#v}" | |
| GIT_SSH_COMMAND='ssh -i ~/.ssh/aur' git push origin master |