Refactor executable path resolution in release workflow for improved … #7
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: Release single-file (server.Stdio) | |
| on: | |
| workflow_dispatch: | |
| push: | |
| tags: | |
| - "v*" | |
| permissions: | |
| contents: write | |
| jobs: | |
| create_release: | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: ${{ github.ref_name }} | |
| draft: false | |
| prerelease: false | |
| generate_release_notes: true | |
| publish: | |
| needs: create_release | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| rid: [ linux-x64, win-x64, osx-arm64 ] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: "9.0.x" | |
| - name: Publish single-file | |
| id: publish | |
| shell: bash | |
| env: | |
| RID: ${{ matrix.rid }} | |
| run: | | |
| set -euo pipefail | |
| PROJ="Server.Stdio/Server.Stdio.csproj" | |
| dotnet publish "$PROJ" -c Release -r "$RID" \ | |
| -p:PublishSingleFile=true \ | |
| -p:SelfContained=true \ | |
| -p:PublishTrimmed=false \ | |
| -p:IncludeNativeLibrariesForSelfExtract=true | |
| TF=$(dotnet msbuild "$PROJ" -getproperty:TargetFramework -nologo -v:quiet) | |
| PUB_DIR="$(dirname "$PROJ")/bin/Release/${TF}/${RID}/publish" | |
| echo "publish_dir=$PUB_DIR" >> "$GITHUB_OUTPUT" | |
| # Find the executable deterministically and resolve to an absolute path | |
| if [[ "$RID" == win* ]]; then | |
| EXE_PATH=$(find "$PUB_DIR" -maxdepth 1 -type f -name "*.exe" -print -quit || true) | |
| else | |
| # Prefer a file named Server.Stdio if present; otherwise any user-executable file | |
| EXE_PATH=$(find "$PUB_DIR" -maxdepth 1 -type f -name "Server.Stdio" -perm -u+x -print -quit || true) | |
| if [ -z "$EXE_PATH" ]; then | |
| EXE_PATH=$(find "$PUB_DIR" -maxdepth 1 -type f -perm -u+x -print -quit || true) | |
| fi | |
| fi | |
| if [ -z "$EXE_PATH" ]; then | |
| echo "No executable found in $PUB_DIR" >&2 | |
| ls -la "$PUB_DIR" || true | |
| exit 1 | |
| fi | |
| # Resolve to absolute path to avoid later path concatenation issues | |
| if command -v readlink >/dev/null 2>&1; then | |
| EXE_ABS=$(readlink -f "$EXE_PATH") | |
| else | |
| EXE_ABS=$(python3 -c 'import os,sys; print(os.path.abspath(sys.argv[1]))' "$EXE_PATH") | |
| fi | |
| echo "exe=$EXE_ABS" >> "$GITHUB_OUTPUT" | |
| echo "Executable: $EXE_ABS" | |
| # Detect sidecar native libraries (needed on some RIDs like macOS) | |
| SIDECAR="" | |
| for pattern in "*.so" "*.dylib"; do | |
| CAND=$(find "$PUB_DIR" -maxdepth 1 -type f -name "$pattern" -print -quit || true) | |
| if [ -n "$CAND" ]; then SIDECAR="$CAND"; break; fi | |
| done | |
| echo "sidecar=$SIDECAR" >> "$GITHUB_OUTPUT" | |
| - name: Prepare native asset | |
| id: package | |
| shell: bash | |
| env: | |
| RID: ${{ matrix.rid }} | |
| TAG: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| EXT=""; [[ "$RID" == win* ]] && EXT=".exe" | |
| BASENAME="mcp-server-stdio-${TAG}-${RID}${EXT}" | |
| SRC="${{ steps.publish.outputs.exe }}" | |
| DEST_DIR="$(mktemp -d)"; DEST="$DEST_DIR/$BASENAME" | |
| cp "$SRC" "$DEST" | |
| chmod +x "$DEST" || true | |
| echo "asset=$DEST" >> "$GITHUB_OUTPUT" | |
| SIDECAR_SRC="${{ steps.publish.outputs.sidecar }}" | |
| if [ -n "$SIDECAR_SRC" ]; then | |
| SNAME="mcp-server-stdio-${TAG}-${RID}-$(basename "$SIDECAR_SRC")" | |
| SC_DEST="$DEST_DIR/$SNAME" | |
| cp "$SIDECAR_SRC" "$SC_DEST" | |
| echo "sidecar_asset=$SC_DEST" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "sidecar_asset=" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Upload executable to GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| files: ${{ steps.package.outputs.asset }} | |
| fail_on_unmatched_files: true | |
| - name: Upload sidecar (if any) to GitHub Release | |
| if: ${{ steps.package.outputs.sidecar_asset != '' }} | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| files: ${{ steps.package.outputs.sidecar_asset }} | |
| fail_on_unmatched_files: true | |
| - name: Upload artifact (native executable) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: io-aerosapce-mcp-${{ github.ref_name }}-${{ matrix.rid }} | |
| path: ${{ steps.package.outputs.asset }} | |
| if-no-files-found: error | |
| - name: Upload artifact (sidecar if any) | |
| if: ${{ steps.package.outputs.sidecar_asset != '' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: io-aerosapce-mcp-${{ github.ref_name }}-${{ matrix.rid }}-sidecar | |
| path: ${{ steps.package.outputs.sidecar_asset }} | |
| if-no-files-found: error |