fix(Oracle): skip watch-only accounts when refreshing response signatures #1039
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: .NET Core Test and Publish | |
| on: | |
| push: | |
| branches: [master-n3] | |
| pull_request: | |
| env: | |
| DOTNET_VERSION: 10.0.x | |
| jobs: | |
| Test: | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup .NET Core | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Check format | |
| if: runner.os == 'Linux' | |
| run: dotnet format --no-restore --verify-no-changes --verbosity diagnostic | |
| - name: Build CLI | |
| if: runner.os == 'Linux' | |
| run: | | |
| dotnet publish -o ./out -c Release src/Neo.CLI | |
| find ./out -name 'config.json' | xargs perl -pi -e 's|LevelDBStore|MemoryStore|g' | |
| - name: Install dependencies | |
| if: runner.os == 'Linux' | |
| run: sudo apt-get install libleveldb-dev expect | |
| - name: Run tests with expect | |
| if: runner.os == 'Linux' | |
| run: expect ./.github/workflows/test-neo-cli.expect | |
| - name: Run Unit Tests | |
| if: runner.os == 'Windows' | |
| run: | | |
| forfiles /p tests /m *.csproj /s /c "cmd /c dotnet add @PATH package coverlet.msbuild" | |
| dotnet test /p:CollectCoverage=true /p:CoverletOutput='${{ github.workspace }}/TestResults/coverage/' /p:MergeWith='${{ github.workspace }}/TestResults/coverage/coverage.json' /p:CoverletOutputFormat=lcov%2cjson -m:1 | |
| - name: Codecov | |
| if: runner.os == 'Windows' | |
| uses: codecov/codecov-action@v6 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ${{ github.workspace }}/TestResults/coverage/coverage.info | |
| fail_ci_if_error: false | |
| Test-with-plugins: | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup .NET Core | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Build CLI | |
| run: | | |
| dotnet build -c Release | |
| dotnet publish -o ./out -c Release src/Neo.CLI | |
| - name: Create Plugins folder and copy plugin DLLs | |
| run: | | |
| mkdir -p ./out/Plugins | |
| for plugin_dir in plugins/*/; do | |
| plugin_name=$(basename "$plugin_dir") | |
| build_output="$plugin_dir/bin/Release/net10.0" | |
| if [ -d "$build_output" ]; then | |
| mkdir -p "./out/Plugins/$plugin_name" | |
| cp -r "$build_output"/* "./out/Plugins/$plugin_name/" | |
| fi | |
| done | |
| # Remove duplicated RpcServer.dll from TokensTracker and StorageDumper (they can't load twice) | |
| rm -f ./out/Plugins/TokensTracker/RpcServer.dll | |
| rm -f ./out/Plugins/StateService/RpcServer.dll | |
| - name: Install dependencies | |
| run: sudo apt-get install -y libleveldb-dev expect | |
| - name: Run tests with expect | |
| run: | | |
| # Count loadable plugins only (exclude MPTTrie dependency and RpcClient library). | |
| expected_count=0 | |
| for csproj in plugins/*/*.csproj; do | |
| plugin_name=$(basename "$(dirname "$csproj")") | |
| case "$plugin_name" in | |
| MPTTrie|RpcClient) continue ;; | |
| esac | |
| expected_count=$((expected_count + 1)) | |
| done | |
| expect ./.github/workflows/test-neo-cli-plugins.expect "$expected_count" | |
| Release: | |
| if: github.ref == 'refs/heads/master-n3' && github.repository == 'neo-project/neo-node' | |
| needs: Test | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| packages: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Get version | |
| id: get_version | |
| run: | | |
| sudo apt install xmlstarlet -qq | |
| # Only release when <Version> is explicitly set (dev builds keep <VersionPrefix> and should not release). | |
| VERSION=$(xmlstarlet sel -N i=http://schemas.microsoft.com/developer/msbuild/2003 -t -v "//i:Version/text()" src/Directory.Build.props 2>/dev/null || echo "") | |
| [ -z "$VERSION" ] && VERSION=$(find plugins -name Directory.Build.props | xargs xmlstarlet sel -N i=http://schemas.microsoft.com/developer/msbuild/2003 -t -v "//i:Version/text()" 2>/dev/null || echo "") | |
| [ -n "$VERSION" ] && echo "version=v$VERSION" >> $GITHUB_OUTPUT || echo "version=" >> $GITHUB_OUTPUT | |
| - name: Check tag | |
| if: steps.get_version.outputs.version != '' && startsWith(steps.get_version.outputs.version, 'v') | |
| id: check_tag | |
| run: curl -s -I ${{ format('https://github.com/{0}/releases/tag/{1}', github.repository, steps.get_version.outputs.version) }} | head -n 1 | cut -d$' ' -f2 | xargs printf "statusCode=%s" | xargs echo >> $GITHUB_OUTPUT | |
| - name: Create release | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if ! gh release view ${{ steps.get_version.outputs.version }} >/dev/null 2>&1; then | |
| if [[ "${{ steps.get_version.outputs.version }}" == *"-"* ]]; then | |
| gh release create ${{ steps.get_version.outputs.version }} \ | |
| --title "${{ steps.get_version.outputs.version }}" \ | |
| --notes "Release ${{ steps.get_version.outputs.version }}" \ | |
| --draft \ | |
| --prerelease | |
| else | |
| gh release create ${{ steps.get_version.outputs.version }} \ | |
| --title "${{ steps.get_version.outputs.version }}" \ | |
| --notes "Release ${{ steps.get_version.outputs.version }}" \ | |
| --draft | |
| fi | |
| fi | |
| - name: Setup .NET Core | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Install zip tool | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| run: sudo apt-get update && sudo apt-get install -y zip | |
| - name: Build LevelDBStore plugin for all platforms | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| run: | | |
| dotnet build plugins/LevelDBStore/LevelDBStore.csproj -c Release | |
| - name: Build and package neo-cli for all platforms | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| env: | |
| RELEASE_VERSION: ${{ steps.get_version.outputs.version }} | |
| run: | | |
| # Define platforms | |
| platforms=("portable" "linux-x64" "linux-arm64" "win-x64" "osx-x64" "osx-arm64") | |
| # LevelDBStore output directory (where native libs are copied after build) | |
| LEVELDB_OUTPUT="plugins/LevelDBStore/bin/Release/net10.0" | |
| # LevelDBStore intermediate directory (where native libs are downloaded) | |
| LEVELDB_OBJ="plugins/LevelDBStore/bin/Release/net10.0/obj/LevelDBStore" | |
| copy_native_lib() { | |
| local rid=$1 | |
| local lib_name=$2 | |
| local target_dir=$3 | |
| local output_path="$LEVELDB_OUTPUT/runtimes/$rid/native/$lib_name" | |
| local obj_path="$LEVELDB_OBJ/libleveldb-$rid/runtimes/$rid/native/$lib_name" | |
| local zip_dir="$LEVELDB_OBJ/libleveldb-$rid" | |
| if [ -f "$output_path" ]; then | |
| cp "$output_path" "$target_dir/" | |
| elif [ -f "$obj_path" ]; then | |
| cp "$obj_path" "$target_dir/" | |
| else | |
| return | |
| fi | |
| # For macOS, also copy any extra .dylib files from the LevelDB package (best-effort) | |
| if [[ "$rid" == osx-* ]] && [ -d "$zip_dir" ]; then | |
| find "$zip_dir" -name "*.dylib" -type f -exec cp {} "$target_dir/" \; 2>/dev/null || true | |
| fi | |
| } | |
| package_publish_output() { | |
| local platform=$1 | |
| local publish_dir="./publish/$platform" | |
| local archive_base="neo-cli.${RELEASE_VERSION}-${platform}" | |
| local package_root="neo-cli-${RELEASE_VERSION}" | |
| local stage_dir="./publish/stage-$platform" | |
| rm -rf "$stage_dir" | |
| mkdir -p "$stage_dir/$package_root" | |
| cp -a "$publish_dir/." "$stage_dir/$package_root/" | |
| case "$platform" in | |
| portable|win-*) | |
| (cd "$stage_dir" && zip -r "../../${archive_base}.zip" "$package_root") | |
| ;; | |
| linux-*|osx-*) | |
| tar -czf "${archive_base}.tar.gz" -C "$stage_dir" "$package_root" | |
| ;; | |
| *) | |
| echo "Error: Unknown platform: $platform" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| rm -rf "$stage_dir" | |
| } | |
| # Traditional framework-dependent publish used only for plugin dependency diffing | |
| dotnet publish src/Neo.CLI/Neo.CLI.csproj -c Release -o "./publish/baseline" --self-contained false | |
| for platform in "${platforms[@]}"; do | |
| if [ "$platform" == "portable" ]; then | |
| rm -rf "./publish/$platform" | |
| cp -a "./publish/baseline" "./publish/$platform" | |
| else | |
| dotnet publish src/Neo.CLI/Neo.CLI.csproj -c Release -o "./publish/$platform" -r "$platform" --self-contained true \ | |
| -p:PublishSingleFile=true \ | |
| -p:IncludeNativeLibrariesForSelfExtract=false \ | |
| -p:DebugType=none \ | |
| -p:DebugSymbols=false | |
| fi | |
| mkdir -p "./publish/$platform/Plugins/LevelDBStore" | |
| cp "$LEVELDB_OUTPUT/LevelDBStore.dll" "./publish/$platform/Plugins/LevelDBStore/" 2>/dev/null || true | |
| if [ "$platform" == "portable" ]; then | |
| copy_native_lib "linux-x64" "libleveldb.so" "./publish/$platform" | |
| copy_native_lib "win-x64" "libleveldb.dll" "./publish/$platform" | |
| copy_native_lib "osx-x64" "libleveldb.dylib" "./publish/$platform" | |
| else | |
| case "$platform" in | |
| "linux-x64"|"linux-arm64") copy_native_lib "$platform" "libleveldb.so" "./publish/$platform" ;; | |
| "win-x64") copy_native_lib "$platform" "libleveldb.dll" "./publish/$platform" ;; | |
| "osx-x64"|"osx-arm64") copy_native_lib "$platform" "libleveldb.dylib" "./publish/$platform" ;; | |
| esac | |
| fi | |
| package_publish_output "$platform" | |
| done | |
| - name: Build and package plugins (zip per plugin) | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| run: | | |
| set -euo pipefail | |
| # Use traditional neo-cli publish output as the baseline set of assemblies (not single-file releases) | |
| if [ ! -d "./publish/baseline" ]; then | |
| echo "Error: ./publish/baseline not found. neo-cli baseline must be published first." | |
| exit 1 | |
| fi | |
| mkdir -p "./plugin-publish" "./plugin-zip" | |
| # Collect baseline DLL filenames shipped with neo-cli | |
| mapfile -t cli_dlls < <(find "./publish/baseline" -maxdepth 1 -type f -name "*.dll" -printf "%f\n" | sort -u) | |
| declare -A cli_dll_set | |
| for f in "${cli_dlls[@]}"; do cli_dll_set["$f"]=1; done | |
| # Package every plugin project under plugins/*/*.csproj (e.g. DeferredRelay), except MPTTrie (StateService dependency only). | |
| for csproj in plugins/*/*.csproj; do | |
| plugin_dir="$(dirname "$csproj")" | |
| plugin_name="$(basename "$plugin_dir")" | |
| # Publish plugin (framework-dependent) to get a clean dependency set | |
| plugin_out="./plugin-publish/$plugin_name" | |
| rm -rf "$plugin_out" | |
| dotnet publish "$csproj" -c Release -o "$plugin_out" --self-contained false | |
| # MPTTrie is only used as a dependency (by StateService). We publish it so that MPTTrie.dll | |
| # exists under plugin-publish/, but we don't stage or zip it as a standalone plugin. | |
| if [ "$plugin_name" == "MPTTrie" ]; then | |
| continue | |
| fi | |
| plugin_json="$plugin_dir/$plugin_name.json" | |
| # Staging layout required by release consumers: | |
| # Plugins/<PluginName>/{PluginName}.dll (+ optional {PluginName}.json) + only required extra dependency dlls | |
| stage_root="./plugin-zip/$plugin_name" | |
| stage_dir="$stage_root/Plugins/$plugin_name" | |
| rm -rf "$stage_root" | |
| mkdir -p "$stage_dir" | |
| # Always include the plugin's own assembly | |
| if [ ! -f "$plugin_out/$plugin_name.dll" ]; then | |
| echo "Error: Missing published plugin dll: $plugin_out/$plugin_name.dll" | |
| exit 1 | |
| fi | |
| cp "$plugin_out/$plugin_name.dll" "$stage_dir/" | |
| # Include plugin json if present | |
| if [ -f "$plugin_json" ]; then | |
| cp "$plugin_json" "$stage_dir/" | |
| fi | |
| # Only include extra dependency DLLs for plugins that explicitly reference NuGet packages. | |
| # This keeps "pure" project-reference plugins (e.g. DBFTPlugin) minimal: {Plugin}.dll (+ optional json). | |
| if grep -q "<PackageReference" "$csproj"; then | |
| # Include only dlls that neo-cli does NOT already ship | |
| shopt -s nullglob | |
| for dep in "$plugin_out"/*.dll; do | |
| dep_name="$(basename "$dep")" | |
| if [ "$dep_name" == "$plugin_name.dll" ]; then | |
| continue | |
| fi | |
| if [ -z "${cli_dll_set["$dep_name"]+x}" ]; then | |
| cp "$dep" "$stage_dir/" | |
| fi | |
| done | |
| shopt -u nullglob | |
| fi | |
| done | |
| # After all plugins are published, ensure StateService staging includes its MPTTrie dependency. | |
| mpt_trie_dll="./plugin-publish/MPTTrie/MPTTrie.dll" | |
| state_stage="./plugin-zip/StateService/Plugins/StateService" | |
| if [ -f "$mpt_trie_dll" ] && [ -d "$state_stage" ]; then | |
| cp "$mpt_trie_dll" "$state_stage/" | |
| fi | |
| # Finally, create zip per plugin from staged directories (excluding MPTTrie by design) | |
| for csproj in plugins/*/*.csproj; do | |
| plugin_dir="$(dirname "$csproj")" | |
| plugin_name="$(basename "$plugin_dir")" | |
| [ "$plugin_name" == "MPTTrie" ] && continue | |
| stage_root="./plugin-zip/$plugin_name" | |
| if [ -d "$stage_root" ]; then | |
| (cd "$stage_root" && zip -r "../../$plugin_name.zip" "Plugins") | |
| fi | |
| done | |
| - name: Upload CLI packages to release | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RELEASE_VERSION: ${{ steps.get_version.outputs.version }} | |
| run: | | |
| RELEASE_TAG="${{ steps.get_version.outputs.version }}" | |
| # Verify release exists | |
| if ! gh release view "$RELEASE_TAG" >/dev/null 2>&1; then | |
| echo "Error: Release $RELEASE_TAG does not exist" | |
| exit 1 | |
| fi | |
| # Verify all required archive files exist | |
| missing_files=() | |
| cli_archives=( | |
| "neo-cli.${RELEASE_VERSION}-portable.zip" | |
| "neo-cli.${RELEASE_VERSION}-linux-x64.tar.gz" | |
| "neo-cli.${RELEASE_VERSION}-linux-arm64.tar.gz" | |
| "neo-cli.${RELEASE_VERSION}-win-x64.zip" | |
| "neo-cli.${RELEASE_VERSION}-osx-x64.tar.gz" | |
| "neo-cli.${RELEASE_VERSION}-osx-arm64.tar.gz" | |
| ) | |
| for file in "${cli_archives[@]}"; do | |
| [ ! -f "$file" ] && missing_files+=("$file") | |
| done | |
| # Verify plugin zip files exist (one per plugins/*/*.csproj, except MPTTrie which is only a dependency) | |
| for csproj in plugins/*/*.csproj; do | |
| plugin_dir="$(dirname "$csproj")" | |
| plugin_name="$(basename "$plugin_dir")" | |
| [ "$plugin_name" == "MPTTrie" ] && continue | |
| [ ! -f "$plugin_name.zip" ] && missing_files+=("$plugin_name.zip") | |
| done | |
| if [ ${#missing_files[@]} -gt 0 ]; then | |
| echo "Error: Missing archive files: ${missing_files[*]}" | |
| exit 1 | |
| fi | |
| # Upload all CLI archives to release | |
| failed_files=() | |
| for file in "${cli_archives[@]}"; do | |
| if ! gh release upload "$RELEASE_TAG" "$file" --clobber; then | |
| failed_files+=("$file") | |
| fi | |
| done | |
| # Upload plugin zip files to release (excluding MPTTrie) | |
| for csproj in plugins/*/*.csproj; do | |
| plugin_dir="$(dirname "$csproj")" | |
| plugin_name="$(basename "$plugin_dir")" | |
| [ "$plugin_name" == "MPTTrie" ] && continue | |
| if ! gh release upload "$RELEASE_TAG" "$plugin_name.zip" --clobber; then | |
| failed_files+=("$plugin_name.zip") | |
| fi | |
| done | |
| if [ ${#failed_files[@]} -gt 0 ]; then | |
| echo "Error: Failed to upload: ${failed_files[*]}" | |
| exit 1 | |
| fi | |
| - name: Publish core packages to NuGet | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| run: | | |
| dotnet pack -o out -c Release | |
| # Push only non-plugin packages here (plugins handled in a separate step) | |
| for pkg in out/*.nupkg; do | |
| name="$(basename "$pkg")" | |
| case "$name" in | |
| Neo.Plugins.*) continue ;; | |
| esac | |
| dotnet nuget push "$pkg" -s https://api.nuget.org/v3/index.json -k "${NUGET_TOKEN}" --skip-duplicate | |
| done | |
| env: | |
| NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }} | |
| - name: Publish plugin packages to NuGet | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| run: | | |
| # Ensure plugin packages are packed (reuse existing 'out' folder to avoid rebuilding everything) | |
| for csproj in plugins/*/*.csproj; do | |
| dotnet pack "$csproj" -c Release -o out | |
| done | |
| # Push all Neo.Plugins.* packages to NuGet.org | |
| for pkg in out/Neo.Plugins.*.nupkg; do | |
| [ -f "$pkg" ] || continue | |
| dotnet nuget push "$pkg" -s https://api.nuget.org/v3/index.json -k "${NUGET_TOKEN}" --skip-duplicate | |
| done | |
| env: | |
| NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }} | |
| # Docker image publish: only on formal release (explicit <Version> → NuGet path), | |
| # not when only <VersionPrefix> is set (MyGet / dev builds). | |
| - name: Set up Docker Buildx | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 | |
| - name: Log in to GitHub Container Registry | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Stage release assets for Docker build | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| env: | |
| RELEASE_VERSION: ${{ steps.get_version.outputs.version }} | |
| run: | | |
| cp "neo-cli.${RELEASE_VERSION}-linux-x64.tar.gz" src/Neo.CLI/Docker/ | |
| cp ApplicationLogs.zip RpcServer.zip TokensTracker.zip src/Neo.CLI/Docker/ | |
| - name: Extract Docker metadata | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| id: docker_meta | |
| uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 | |
| with: | |
| images: ghcr.io/${{ github.repository }} | |
| tags: | | |
| type=raw,value=${{ steps.get_version.outputs.version }} | |
| type=raw,value=latest,enable=${{ !contains(steps.get_version.outputs.version, '-') }} | |
| - name: Build and push Docker image | |
| if: steps.check_tag.outputs.statusCode == '404' | |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 | |
| with: | |
| context: src/Neo.CLI/Docker | |
| push: true | |
| tags: ${{ steps.docker_meta.outputs.tags }} | |
| labels: ${{ steps.docker_meta.outputs.labels }} | |
| build-args: | | |
| CLI_VERSION=${{ steps.get_version.outputs.version }} | |
| GITHUB_REPO=${{ github.repository }} |