name: CI
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
schedule:
- cron: 0 0 * * *
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
daily-gate:
name: Daily Run Gate
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
outputs:
should_run: ${{ steps.gate.outputs.should_run }}
steps:
- name: Allow only one CI run per UTC day
id: gate
uses: actions/github-script@v7
with:
script: "const owner = context.repo.owner;\nconst repo = context.repo.repo;\n\
const workflow_id = 'ci.yml';\nconst now = new Date();\nconst startOfUtcDay\
\ = new Date(Date.UTC(\n now.getUTCFullYear(),\n now.getUTCMonth(),\n\
\ now.getUTCDate(),\n 0, 0, 0\n));\n\nconst { data } = await github.rest.actions.listWorkflowRuns({\n\
\ owner,\n repo,\n workflow_id,\n per_page: 100\n});\n\nconst runsToday\
\ = data.workflow_runs.filter((run) => {\n if (run.id === context.runId)\
\ return false;\n const createdAt = new Date(run.created_at);\n return\
\ createdAt >= startOfUtcDay;\n});\n\nconst shouldRun = context.eventName\
\ !== 'schedule' || runsToday.length === 0;\ncore.info(`Event: ${context.eventName}.\
\ Found ${runsToday.length} existing CI run(s) today (UTC).`);\ncore.setOutput('should_run',\
\ shouldRun ? 'true' : 'false');\n"
timeout-minutes: 15
core:
name: Core CI
needs: daily-gate
if: needs.daily-gate.outputs.should_run == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache Cargo dependencies
uses: actions/cache@v4
with:
path: "~/.cargo/registry
~/.cargo/git
target
"
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: "${{ runner.os }}-cargo-
"
- name: Check formatting
run: cargo fmt --all -- --check
- name: Run Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Run tests
run: cargo test --workspace --all-features
- name: Build release binary
run: cargo build --release
- name: Compile smoke contract
run: "./target/release/neo-solc examples/ERC20Token.sol -o SmokeERC20 -v
test -f SmokeERC20.nef
test -f SmokeERC20.manifest.json
"
- name: Validate emitted artifacts
run: 'MAGIC=$(xxd -l 4 -p SmokeERC20.nef)
test "$MAGIC" = "4e454633"
python3 -c "import json; d=json.load(open(''SmokeERC20.manifest.json''));
assert d.get(''name''); assert ''abi'' in d; assert ''permissions'' in d"
'
neoxp-smoke:
name: Neo-Express On-Chain Smoke (subset)
needs: daily-gate
if: needs.daily-gate.outputs.should_run == 'true'
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-smoke-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-smoke-
- name: Build neo-solc (release)
run: cargo build --release --bin neo-solc
- name: Install .NET SDK (for Neo-Express)
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Install Neo-Express + jq
run: |
dotnet tool install Neo.Express --tool-path "$PWD/build/dotnet-tools"
echo "$PWD/build/dotnet-tools" >> "$GITHUB_PATH"
sudo apt-get update -qq
sudo apt-get install -y -qq jq xxd
- name: Pin neo-solc binary for the smoke scripts
run: echo "NEO_SOLC=$PWD/target/release/neo-solc" >> "$GITHUB_ENV"
- name: Run representative Neo-Express smoke subset
run: |
set -e
for t in deploy callt_smoke constructor_smoke encoding_smoke permissions_smoke; do
echo "::group::test_neoxp_${t}.sh"
bash "examples/test_neoxp_${t}.sh"
echo "::endgroup::"
done