9595 id : get_version
9696 run : |
9797 sudo apt install xmlstarlet -qq
98+ # Only release when <Version> is explicitly set (dev builds keep <VersionPrefix> and should not release).
9899 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 "")
99100 [ -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 "")
100101 [ -n "$VERSION" ] && echo "version=v$VERSION" >> $GITHUB_OUTPUT || echo "version=" >> $GITHUB_OUTPUT
@@ -190,6 +191,96 @@ jobs:
190191
191192 cd "./publish/$platform" && zip -r "../../neo-cli-$platform.zip" . && cd ../..
192193 done
194+
195+ - name : Build and package plugins (zip per plugin)
196+ if : steps.check_tag.outputs.statusCode == '404'
197+ run : |
198+ set -euo pipefail
199+
200+ # Use neo-cli portable publish output as the baseline set of assemblies
201+ if [ ! -d "./publish/portable" ]; then
202+ echo "Error: ./publish/portable not found. neo-cli portable must be published first."
203+ exit 1
204+ fi
205+
206+ mkdir -p "./plugin-publish" "./plugin-zip"
207+
208+ # Collect baseline DLL filenames shipped with neo-cli portable
209+ mapfile -t cli_dlls < <(find "./publish/portable" -maxdepth 1 -type f -name "*.dll" -printf "%f\n" | sort -u)
210+ declare -A cli_dll_set
211+ for f in "${cli_dlls[@]}"; do cli_dll_set["$f"]=1; done
212+
213+ # Package every plugin project under plugins/*/*.csproj (stage only, zip after all are staged)
214+ for csproj in plugins/*/*.csproj; do
215+ plugin_dir="$(dirname "$csproj")"
216+ plugin_name="$(basename "$plugin_dir")"
217+ # Publish plugin (framework-dependent) to get a clean dependency set
218+ plugin_out="./plugin-publish/$plugin_name"
219+ rm -rf "$plugin_out"
220+ dotnet publish "$csproj" -c Release -o "$plugin_out" --self-contained false
221+
222+ # MPTTrie is only used as a dependency (by StateService). We publish it so that MPTTrie.dll
223+ # exists under plugin-publish/, but we don't stage or zip it as a standalone plugin.
224+ if [ "$plugin_name" == "MPTTrie" ]; then
225+ continue
226+ fi
227+
228+ plugin_json="$plugin_dir/$plugin_name.json"
229+
230+ # Staging layout required by release consumers:
231+ # Plugins/<PluginName>/{PluginName}.dll (+ optional {PluginName}.json) + only required extra dependency dlls
232+ stage_root="./plugin-zip/$plugin_name"
233+ stage_dir="$stage_root/Plugins/$plugin_name"
234+ rm -rf "$stage_root"
235+ mkdir -p "$stage_dir"
236+
237+ # Always include the plugin's own assembly
238+ if [ ! -f "$plugin_out/$plugin_name.dll" ]; then
239+ echo "Error: Missing published plugin dll: $plugin_out/$plugin_name.dll"
240+ exit 1
241+ fi
242+ cp "$plugin_out/$plugin_name.dll" "$stage_dir/"
243+
244+ # Include plugin json if present
245+ if [ -f "$plugin_json" ]; then
246+ cp "$plugin_json" "$stage_dir/"
247+ fi
248+
249+ # Only include extra dependency DLLs for plugins that explicitly reference NuGet packages.
250+ # This keeps "pure" project-reference plugins (e.g. DBFTPlugin) minimal: {Plugin}.dll (+ optional json).
251+ if grep -q "<PackageReference" "$csproj"; then
252+ # Include only dlls that neo-cli portable does NOT already ship
253+ shopt -s nullglob
254+ for dep in "$plugin_out"/*.dll; do
255+ dep_name="$(basename "$dep")"
256+ if [ "$dep_name" == "$plugin_name.dll" ]; then
257+ continue
258+ fi
259+ if [ -z "${cli_dll_set["$dep_name"]+x}" ]; then
260+ cp "$dep" "$stage_dir/"
261+ fi
262+ done
263+ shopt -u nullglob
264+ fi
265+ done
266+
267+ # After all plugins are published, ensure StateService staging includes its MPTTrie dependency.
268+ mpt_trie_dll="./plugin-publish/MPTTrie/MPTTrie.dll"
269+ state_stage="./plugin-zip/StateService/Plugins/StateService"
270+ if [ -f "$mpt_trie_dll" ] && [ -d "$state_stage" ]; then
271+ cp "$mpt_trie_dll" "$state_stage/"
272+ fi
273+
274+ # Finally, create zip per plugin from staged directories (excluding MPTTrie by design)
275+ for csproj in plugins/*/*.csproj; do
276+ plugin_dir="$(dirname "$csproj")"
277+ plugin_name="$(basename "$plugin_dir")"
278+ [ "$plugin_name" == "MPTTrie" ] && continue
279+ stage_root="./plugin-zip/$plugin_name"
280+ if [ -d "$stage_root" ]; then
281+ (cd "$stage_root" && zip -r "../../$plugin_name.zip" "Plugins")
282+ fi
283+ done
193284 - name : Upload CLI packages to release
194285 if : steps.check_tag.outputs.statusCode == '404'
195286 env :
@@ -208,6 +299,14 @@ jobs:
208299 for file in neo-cli-portable.zip neo-cli-linux-x64.zip neo-cli-linux-arm64.zip neo-cli-win-x64.zip neo-cli-osx-x64.zip neo-cli-osx-arm64.zip; do
209300 [ ! -f "$file" ] && missing_files+=("$file")
210301 done
302+
303+ # Verify plugin zip files exist (one per plugins/*/*.csproj, except MPTTrie which is only a dependency)
304+ for csproj in plugins/*/*.csproj; do
305+ plugin_dir="$(dirname "$csproj")"
306+ plugin_name="$(basename "$plugin_dir")"
307+ [ "$plugin_name" == "MPTTrie" ] && continue
308+ [ ! -f "$plugin_name.zip" ] && missing_files+=("$plugin_name.zip")
309+ done
211310
212311 if [ ${#missing_files[@]} -gt 0 ]; then
213312 echo "Error: Missing zip files: ${missing_files[*]}"
@@ -221,15 +320,49 @@ jobs:
221320 failed_files+=("$file")
222321 fi
223322 done
323+
324+ # Upload plugin zip files to release (excluding MPTTrie)
325+ for csproj in plugins/*/*.csproj; do
326+ plugin_dir="$(dirname "$csproj")"
327+ plugin_name="$(basename "$plugin_dir")"
328+ [ "$plugin_name" == "MPTTrie" ] && continue
329+ if ! gh release upload "$RELEASE_TAG" "$plugin_name.zip" --clobber; then
330+ failed_files+=("$plugin_name.zip")
331+ fi
332+ done
224333
225334 if [ ${#failed_files[@]} -gt 0 ]; then
226335 echo "Error: Failed to upload: ${failed_files[*]}"
227336 exit 1
228337 fi
229- - name : Publish to NuGet
338+ - name : Publish core packages to NuGet
230339 if : steps.check_tag.outputs.statusCode == '404'
231340 run : |
232341 dotnet pack -o out -c Release
233- dotnet nuget push out/*.nupkg -s https://api.nuget.org/v3/index.json -k ${NUGET_TOKEN}
342+
343+ # Push only non-plugin packages here (plugins handled in a separate step)
344+ for pkg in out/*.nupkg; do
345+ name="$(basename "$pkg")"
346+ case "$name" in
347+ Neo.Plugins.*) continue ;;
348+ esac
349+ dotnet nuget push "$pkg" -s https://api.nuget.org/v3/index.json -k "${NUGET_TOKEN}" --skip-duplicate
350+ done
351+ env :
352+ NUGET_TOKEN : ${{ secrets.NUGET_TOKEN }}
353+
354+ - name : Publish plugin packages to NuGet
355+ if : steps.check_tag.outputs.statusCode == '404'
356+ run : |
357+ # Ensure plugin packages are packed (reuse existing 'out' folder to avoid rebuilding everything)
358+ for csproj in plugins/*/*.csproj; do
359+ dotnet pack "$csproj" -c Release -o out
360+ done
361+
362+ # Push all Neo.Plugins.* packages to NuGet.org
363+ for pkg in out/Neo.Plugins.*.nupkg; do
364+ [ -f "$pkg" ] || continue
365+ dotnet nuget push "$pkg" -s https://api.nuget.org/v3/index.json -k "${NUGET_TOKEN}" --skip-duplicate
366+ done
234367 env :
235368 NUGET_TOKEN : ${{ secrets.NUGET_TOKEN }}
0 commit comments