From de167504f59de5915291e59de6cd68a2b35fc93e Mon Sep 17 00:00:00 2001 From: Eddy Moulton Date: Tue, 28 Apr 2026 11:35:27 +1000 Subject: [PATCH 1/7] octopus/em/attempt-bundling-for-mac --- build.libgit2.sh | 50 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/build.libgit2.sh b/build.libgit2.sh index d8ed8744..0bd5a634 100755 --- a/build.libgit2.sh +++ b/build.libgit2.sh @@ -62,7 +62,55 @@ cp libgit2/build/libgit2-$SHORTSHA.$LIBEXT $PACKAGEPATH/$RID/native LIBGIT2_PATH="$PACKAGEPATH/$RID/native/libgit2-$SHORTSHA.$LIBEXT" if [[ $OS == "Darwin" ]]; then - echo "macOS: libssh2 sourced from global installation" + NATIVE_DIR="$PACKAGEPATH/$RID/native" + + is_homebrew_path() { + case "$1" in + /opt/homebrew/*|/usr/local/Cellar/*|/usr/local/opt/*) return 0 ;; + *) return 1 ;; + esac + } + + # Walk the load commands of $1 and, for each Homebrew-rooted dep, copy it next to libgit2, + # rewrite the load command to @rpath, and recurse so transitive deps (libssl -> libcrypto, etc.) are covered. + bundle_homebrew_deps() { + local DYLIB="$1" + local DEPS + DEPS=$(otool -L "$DYLIB" | tail -n +2 | awk '{print $1}') + local DEP + for DEP in $DEPS; do + if is_homebrew_path "$DEP"; then + local DEP_BASENAME + DEP_BASENAME=$(basename "$DEP") + local DEP_DEST="$NATIVE_DIR/$DEP_BASENAME" + if [[ ! -f "$DEP_DEST" ]]; then + echo "Bundling $DEP_BASENAME from $DEP" + cp "$DEP" "$DEP_DEST" + chmod u+w "$DEP_DEST" + install_name_tool -id "@rpath/$DEP_BASENAME" "$DEP_DEST" + bundle_homebrew_deps "$DEP_DEST" + fi + install_name_tool -change "$DEP" "@rpath/$DEP_BASENAME" "$DYLIB" + fi + done + } + + bundle_homebrew_deps "$LIBGIT2_PATH" + + # Fallback rpaths so the binary still loads if a user has libssh2 elsewhere on their system. + for DYLIB in "$NATIVE_DIR"/*.dylib; do + install_name_tool -add_rpath @loader_path "$DYLIB" + # install_name_tool -add_rpath /opt/homebrew/lib "$DYLIB" + # install_name_tool -add_rpath /opt/homebrew/opt/libssh2/lib "$DYLIB" + # install_name_tool -add_rpath /usr/local/lib "$DYLIB" + # install_name_tool -add_rpath /usr/local/opt/libssh2/lib "$DYLIB" + # install_name_tool -add_rpath /opt/local/lib "$DYLIB" + done + + # Ad-hoc re-sign — install_name_tool invalidates the existing signature, which is fatal on Apple Silicon. + for DYLIB in "$NATIVE_DIR"/*.dylib; do + codesign --force --sign - "$DYLIB" + done" else # Linux: find libssh2 via ldd LIBSSH2_PATH=$(ldd "$LIBGIT2_PATH" | grep libssh2 | awk '{print $3}') From 9e33849f7654d6ee51fed6bbf950c5792f9e6f78 Mon Sep 17 00:00:00 2001 From: Eddy Moulton Date: Tue, 28 Apr 2026 11:44:37 +1000 Subject: [PATCH 2/7] Fix bad merge --- build.libgit2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.libgit2.sh b/build.libgit2.sh index 0bd5a634..b24c22f2 100755 --- a/build.libgit2.sh +++ b/build.libgit2.sh @@ -110,7 +110,7 @@ if [[ $OS == "Darwin" ]]; then # Ad-hoc re-sign — install_name_tool invalidates the existing signature, which is fatal on Apple Silicon. for DYLIB in "$NATIVE_DIR"/*.dylib; do codesign --force --sign - "$DYLIB" - done" + done else # Linux: find libssh2 via ldd LIBSSH2_PATH=$(ldd "$LIBGIT2_PATH" | grep libssh2 | awk '{print $3}') From 2b73559929e6bd7e5723b5b1d1b63c179251dab7 Mon Sep 17 00:00:00 2001 From: Eddy Moulton Date: Thu, 30 Apr 2026 16:33:13 +1000 Subject: [PATCH 3/7] Remove unneeded paths --- build.libgit2.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build.libgit2.sh b/build.libgit2.sh index b24c22f2..ecc58f50 100755 --- a/build.libgit2.sh +++ b/build.libgit2.sh @@ -100,11 +100,6 @@ if [[ $OS == "Darwin" ]]; then # Fallback rpaths so the binary still loads if a user has libssh2 elsewhere on their system. for DYLIB in "$NATIVE_DIR"/*.dylib; do install_name_tool -add_rpath @loader_path "$DYLIB" - # install_name_tool -add_rpath /opt/homebrew/lib "$DYLIB" - # install_name_tool -add_rpath /opt/homebrew/opt/libssh2/lib "$DYLIB" - # install_name_tool -add_rpath /usr/local/lib "$DYLIB" - # install_name_tool -add_rpath /usr/local/opt/libssh2/lib "$DYLIB" - # install_name_tool -add_rpath /opt/local/lib "$DYLIB" done # Ad-hoc re-sign — install_name_tool invalidates the existing signature, which is fatal on Apple Silicon. From 83c23daa0e94e7b1ef29829d6e8bc7134f691e11 Mon Sep 17 00:00:00 2001 From: Eddy Moulton Date: Fri, 1 May 2026 08:57:08 +1000 Subject: [PATCH 4/7] comments --- build.libgit2.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.libgit2.sh b/build.libgit2.sh index ecc58f50..c42f8ba8 100755 --- a/build.libgit2.sh +++ b/build.libgit2.sh @@ -62,6 +62,8 @@ cp libgit2/build/libgit2-$SHORTSHA.$LIBEXT $PACKAGEPATH/$RID/native LIBGIT2_PATH="$PACKAGEPATH/$RID/native/libgit2-$SHORTSHA.$LIBEXT" if [[ $OS == "Darwin" ]]; then + # We don't run Octopus Server on Mac, so we can avoid the restriction of relying on the system crypto libraries + # (Required for FIPS compliance). Instead we just bundle the packages so devs don't need to install them. NATIVE_DIR="$PACKAGEPATH/$RID/native" is_homebrew_path() { @@ -97,9 +99,8 @@ if [[ $OS == "Darwin" ]]; then bundle_homebrew_deps "$LIBGIT2_PATH" - # Fallback rpaths so the binary still loads if a user has libssh2 elsewhere on their system. for DYLIB in "$NATIVE_DIR"/*.dylib; do - install_name_tool -add_rpath @loader_path "$DYLIB" + install_name_tool -add_rpath @loader_path "$DYLIB" done # Ad-hoc re-sign — install_name_tool invalidates the existing signature, which is fatal on Apple Silicon. From d0037b08cfd8be7ed680ada37794cd50df37b6a5 Mon Sep 17 00:00:00 2001 From: Eddy Moulton <8491021+eddymoulton@users.noreply.github.com> Date: Thu, 7 May 2026 11:41:48 +1000 Subject: [PATCH 5/7] Update build.libgit2.sh Co-authored-by: Liam Mackie --- build.libgit2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.libgit2.sh b/build.libgit2.sh index c42f8ba8..d8edaaf9 100755 --- a/build.libgit2.sh +++ b/build.libgit2.sh @@ -68,7 +68,7 @@ if [[ $OS == "Darwin" ]]; then is_homebrew_path() { case "$1" in - /opt/homebrew/*|/usr/local/Cellar/*|/usr/local/opt/*) return 0 ;; + /opt/homebrew/*|/usr/local/Cellar/*) return 0 ;; *) return 1 ;; esac } From 1b36be5df9a58d5ed235b0616b033721d032829f Mon Sep 17 00:00:00 2001 From: Eddy Moulton Date: Thu, 7 May 2026 13:30:08 +1000 Subject: [PATCH 6/7] Fix prerelease versioning --- .github/workflows/ci.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3a67326..5f764f76 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,20 +84,25 @@ jobs: uses: actions/setup-dotnet@v5.2.0 with: dotnet-version: 9.0.x - - name: Compute version suffix for branch builds + - name: Compute version override for branch builds if: ${{ !startsWith(github.ref, 'refs/tags/') }} id: version run: | + # Base version = latest release tag (MAJOR.MINOR.PATCH) with patch bumped + LATEST=$(git tag --list --sort=-v:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1) + PATCH=${LATEST##*.} + MAJOR_MINOR=${LATEST%.*} + BASE="${MAJOR_MINOR}.$((PATCH + 1))" # Sanitize branch name: lowercase, replace non-alphanumeric with hyphen, trim to 20 chars BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" SAFE_BRANCH=$(echo "$BRANCH" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//' | cut -c1-20) - echo "override=${SAFE_BRANCH}.${{ github.run_number }}" >> "$GITHUB_OUTPUT" + echo "override=${BASE}-${SAFE_BRANCH}.${{ github.run_number }}" >> "$GITHUB_OUTPUT" - name: Download artifacts uses: actions/download-artifact@v8.0.1 with: path: nuget.package/runtimes/ - name: Create package - run: dotnet pack nuget.package ${{ steps.version.outputs.override && format('/p:MinVerDefaultPreReleaseIdentifiers="{0}"', steps.version.outputs.override) || '' }} + run: dotnet pack nuget.package ${{ steps.version.outputs.override && format('/p:MinVerVersionOverride={0}', steps.version.outputs.override) || '' }} - name: Upload NuGet package uses: actions/upload-artifact@v7.0.0 with: From f498899c26e8d67752036d2aff7bc54c3550be2d Mon Sep 17 00:00:00 2001 From: Eddy Moulton Date: Thu, 7 May 2026 14:07:12 +1000 Subject: [PATCH 7/7] Base last version off our actual tag --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f764f76..a758e275 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,15 +88,17 @@ jobs: if: ${{ !startsWith(github.ref, 'refs/tags/') }} id: version run: | - # Base version = latest release tag (MAJOR.MINOR.PATCH) with patch bumped - LATEST=$(git tag --list --sort=-v:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1) - PATCH=${LATEST##*.} - MAJOR_MINOR=${LATEST%.*} - BASE="${MAJOR_MINOR}.$((PATCH + 1))" + # Latest release tag matching the convention -octopus. (see README "Releasing") + LATEST=$(git tag --list --sort=-v:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+-octopus\.[0-9]+$' | head -n 1) + if [ -z "$LATEST" ]; then + echo "::error::No release tag matching -octopus. found" + exit 1 + fi # Sanitize branch name: lowercase, replace non-alphanumeric with hyphen, trim to 20 chars BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" SAFE_BRANCH=$(echo "$BRANCH" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//' | cut -c1-20) - echo "override=${BASE}-${SAFE_BRANCH}.${{ github.run_number }}" >> "$GITHUB_OUTPUT" + # Join with '.' (not '-') so branch/run land as separate prerelease IDs, keeping ordering correct vs the next octopus. + echo "override=${LATEST}.${SAFE_BRANCH}.${{ github.run_number }}" >> "$GITHUB_OUTPUT" - name: Download artifacts uses: actions/download-artifact@v8.0.1 with: