diff --git a/.github/macos-installer/Makefile b/.github/macos-installer/Makefile
new file mode 100644
index 00000000000000..3e1d60dcbeb2ef
--- /dev/null
+++ b/.github/macos-installer/Makefile
@@ -0,0 +1,157 @@
+SHELL := /bin/bash
+SUDO := sudo
+C_INCLUDE_PATH := /usr/include
+CPLUS_INCLUDE_PATH := /usr/include
+LD_LIBRARY_PATH := /usr/lib
+
+OSX_VERSION := $(shell sw_vers -productVersion)
+TARGET_FLAGS := -mmacosx-version-min=$(OSX_VERSION) -DMACOSX_DEPLOYMENT_TARGET=$(OSX_VERSION)
+
+uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
+
+ARCH_UNIV := universal
+ARCH_FLAGS := -arch x86_64 -arch arm64
+
+CFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS)
+LDFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS)
+
+PREFIX := /usr/local
+GIT_PREFIX := $(PREFIX)/git
+
+BUILD_DIR := $(GITHUB_WORKSPACE)/payload
+DESTDIR := $(PWD)/stage/git-$(ARCH_UNIV)-$(VERSION)
+ARTIFACTDIR := build-artifacts
+SUBMAKE := $(MAKE) C_INCLUDE_PATH="$(C_INCLUDE_PATH)" CPLUS_INCLUDE_PATH="$(CPLUS_INCLUDE_PATH)" LD_LIBRARY_PATH="$(LD_LIBRARY_PATH)" TARGET_FLAGS="$(TARGET_FLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" NO_GETTEXT=1 NO_DARWIN_PORTS=1 prefix=$(GIT_PREFIX) DESTDIR=$(DESTDIR)
+CORES := $(shell bash -c "sysctl hw.ncpu | awk '{print \$$2}'")
+
+# Guard against environment variables
+APPLE_APP_IDENTITY =
+APPLE_INSTALLER_IDENTITY =
+APPLE_KEYCHAIN_PROFILE =
+
+.PHONY: image pkg payload codesign notarize
+
+.SECONDARY:
+
+$(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV):
+ rm -f $(BUILD_DIR)/git-$(VERSION)/osx-installed*
+ mkdir -p $(DESTDIR)$(GIT_PREFIX)
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-built-keychain:
+ cd $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain; $(SUBMAKE) CFLAGS="$(CFLAGS) -g -O2 -Wall"
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-built:
+ [ -d $(DESTDIR)$(GIT_PREFIX) ] && $(SUDO) rm -rf $(DESTDIR) || echo ok
+ cd $(BUILD_DIR)/git-$(VERSION); $(SUBMAKE) -j $(CORES) all strip
+ echo "================"
+ echo "Dumping Linkage"
+ cd $(BUILD_DIR)/git-$(VERSION); ./git version
+ echo "===="
+ cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git
+ echo "===="
+ cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-http-fetch
+ echo "===="
+ cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-http-push
+ echo "===="
+ cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-remote-http
+ echo "===="
+ cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-gvfs-helper
+ echo "================"
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-installed-bin: $(BUILD_DIR)/git-$(VERSION)/osx-built $(BUILD_DIR)/git-$(VERSION)/osx-built-keychain
+ cd $(BUILD_DIR)/git-$(VERSION); $(SUBMAKE) install
+ cp $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain $(DESTDIR)$(GIT_PREFIX)/bin/git-credential-osxkeychain
+ mkdir -p $(DESTDIR)$(GIT_PREFIX)/contrib/completion
+ cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-completion.bash $(DESTDIR)$(GIT_PREFIX)/contrib/completion/
+ cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-completion.zsh $(DESTDIR)$(GIT_PREFIX)/contrib/completion/
+ cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-prompt.sh $(DESTDIR)$(GIT_PREFIX)/contrib/completion/
+ # This is needed for Git-Gui, GitK
+ mkdir -p $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl
+ [ ! -f $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl/Error.pm ] && cp $(BUILD_DIR)/git-$(VERSION)/perl/private-Error.pm $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl/Error.pm || echo done
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-installed-man: $(BUILD_DIR)/git-$(VERSION)/osx-installed-bin
+ mkdir -p $(DESTDIR)$(GIT_PREFIX)/share/man
+ cp -R $(GITHUB_WORKSPACE)/manpages/ $(DESTDIR)$(GIT_PREFIX)/share/man
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-built-subtree:
+ cd $(BUILD_DIR)/git-$(VERSION)/contrib/subtree; $(SUBMAKE) XML_CATALOG_FILES="$(XML_CATALOG_FILES)" all git-subtree.1
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree: $(BUILD_DIR)/git-$(VERSION)/osx-built-subtree
+ mkdir -p $(DESTDIR)
+ cd $(BUILD_DIR)/git-$(VERSION)/contrib/subtree; $(SUBMAKE) XML_CATALOG_FILES="$(XML_CATALOG_FILES)" install install-man
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-installed-assets: $(BUILD_DIR)/git-$(VERSION)/osx-installed-bin
+ mkdir -p $(DESTDIR)$(GIT_PREFIX)/etc
+ cat assets/etc/gitconfig.osxkeychain >> $(DESTDIR)$(GIT_PREFIX)/etc/gitconfig
+ cp assets/uninstall.sh $(DESTDIR)$(GIT_PREFIX)/uninstall.sh
+ sh -c "echo .DS_Store >> $(DESTDIR)$(GIT_PREFIX)/share/git-core/templates/info/exclude"
+
+symlinks:
+ mkdir -p $(ARTIFACTDIR)$(PREFIX)/bin
+ cd $(ARTIFACTDIR)$(PREFIX)/bin; find ../git/bin -type f -exec ln -sf {} \;
+ for man in man1 man3 man5 man7; do mkdir -p $(ARTIFACTDIR)$(PREFIX)/share/man/$$man; (cd $(ARTIFACTDIR)$(PREFIX)/share/man/$$man; ln -sf ../../../git/share/man/$$man/* ./); done
+ ruby ../scripts/symlink-git-hardlinks.rb $(ARTIFACTDIR)
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-installed: $(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV) $(BUILD_DIR)/git-$(VERSION)/osx-installed-man $(BUILD_DIR)/git-$(VERSION)/osx-installed-assets $(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree
+ find $(DESTDIR)$(GIT_PREFIX) -type d -exec chmod ugo+rx {} \;
+ find $(DESTDIR)$(GIT_PREFIX) -type f -exec chmod ugo+r {} \;
+ touch $@
+
+$(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV): $(BUILD_DIR)/git-$(VERSION)/osx-built
+ File $(BUILD_DIR)/git-$(VERSION)/git
+ File $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain
+ touch $@
+
+disk-image/VERSION-$(VERSION)-$(ARCH_UNIV):
+ rm -f disk-image/*.pkg disk-image/VERSION-* disk-image/.DS_Store
+ mkdir disk-image
+ touch "$@"
+
+pkg_cmd := pkgbuild --identifier com.git.pkg --version $(VERSION) \
+ --root $(ARTIFACTDIR)$(PREFIX) --scripts assets/scripts \
+ --install-location $(PREFIX) --component-plist ./assets/git-components.plist
+
+ifdef APPLE_INSTALLER_IDENTITY
+ pkg_cmd += --sign "$(APPLE_INSTALLER_IDENTITY)"
+endif
+
+pkg_cmd += disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg
+disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg: disk-image/VERSION-$(VERSION)-$(ARCH_UNIV) symlinks
+ $(pkg_cmd)
+
+git-%-$(ARCH_UNIV).dmg:
+ hdiutil create git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) $(ARCH_UNIV)" -ov 2>&1 | tee err || { \
+ grep "Resource busy" err && \
+ sleep 5 && \
+ hdiutil create git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) $(ARCH_UNIV)" -ov; }
+ hdiutil convert -format UDZO -o $@ git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg
+ rm -f git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg
+
+payload: $(BUILD_DIR)/git-$(VERSION)/osx-installed $(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV)
+
+pkg: disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg
+
+image: git-$(VERSION)-$(ARCH_UNIV).dmg
+
+ifdef APPLE_APP_IDENTITY
+codesign:
+ @$(CURDIR)/../scripts/codesign.sh --payload="build-artifacts/usr/local/git" \
+ --identity="$(APPLE_APP_IDENTITY)" \
+ --entitlements="$(CURDIR)/entitlements.xml"
+endif
+
+# Notarization can only happen if the package is fully signed
+ifdef APPLE_KEYCHAIN_PROFILE
+notarize:
+ @$(CURDIR)/../scripts/notarize.sh \
+ --package="disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg" \
+ --keychain-profile="$(APPLE_KEYCHAIN_PROFILE)"
+endif
diff --git a/.github/macos-installer/assets/etc/gitconfig.osxkeychain b/.github/macos-installer/assets/etc/gitconfig.osxkeychain
new file mode 100644
index 00000000000000..788266b3a40a9d
--- /dev/null
+++ b/.github/macos-installer/assets/etc/gitconfig.osxkeychain
@@ -0,0 +1,2 @@
+[credential]
+ helper = osxkeychain
diff --git a/.github/macos-installer/assets/git-components.plist b/.github/macos-installer/assets/git-components.plist
new file mode 100644
index 00000000000000..78db36777df3ed
--- /dev/null
+++ b/.github/macos-installer/assets/git-components.plist
@@ -0,0 +1,18 @@
+
+
+
+
+
+ BundleHasStrictIdentifier
+
+ BundleIsRelocatable
+
+ BundleIsVersionChecked
+
+ BundleOverwriteAction
+ upgrade
+ RootRelativeBundlePath
+ git/share/git-gui/lib/Git Gui.app
+
+
+
diff --git a/.github/macos-installer/assets/scripts/postinstall b/.github/macos-installer/assets/scripts/postinstall
new file mode 100755
index 00000000000000..94056db9b7b864
--- /dev/null
+++ b/.github/macos-installer/assets/scripts/postinstall
@@ -0,0 +1,62 @@
+#!/bin/bash
+INSTALL_DST="$2"
+SCALAR_C_CMD="$INSTALL_DST/git/bin/scalar"
+SCALAR_DOTNET_CMD="/usr/local/scalar/scalar"
+SCALAR_UNINSTALL_SCRIPT="/usr/local/scalar/uninstall_scalar.sh"
+
+function cleanupScalar()
+{
+ echo "checking whether Scalar was installed"
+ if [ ! -f "$SCALAR_C_CMD" ]; then
+ echo "Scalar not installed; exiting..."
+ return 0
+ fi
+ echo "Scalar is installed!"
+
+ echo "looking for Scalar.NET"
+ if [ ! -f "$SCALAR_DOTNET_CMD" ]; then
+ echo "Scalar.NET not found; exiting..."
+ return 0
+ fi
+ echo "Scalar.NET found!"
+
+ currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
+
+ # Re-register Scalar.NET repositories with the newly-installed Scalar
+ for repo in $($SCALAR_DOTNET_CMD list); do
+ (
+ PATH="$INSTALL_DST/git/bin:$PATH"
+ sudo -u "$currentUser" scalar register $repo || \
+ echo "warning: skipping re-registration of $repo"
+ )
+ done
+
+ # Uninstall Scalar.NET
+ echo "removing Scalar.NET"
+
+ # Add /usr/local/bin to path - default install location of Homebrew
+ PATH="/usr/local/bin:$PATH"
+ if (sudo -u "$currentUser" brew list --cask scalar); then
+ # Remove from Homebrew
+ sudo -u "$currentUser" brew remove --cask scalar || echo "warning: Scalar.NET uninstall via Homebrew completed with code $?"
+ echo "Scalar.NET uninstalled via Homebrew!"
+ elif (sudo -u "$currentUser" brew list --cask scalar-azrepos); then
+ sudo -u "$currentUser" brew remove --cask scalar-azrepos || echo "warning: Scalar.NET with GVFS uninstall via Homebrew completed with code $?"
+ echo "Scalar.NET with GVFS uninstalled via Homebrew!"
+ elif [ -f $SCALAR_UNINSTALL_SCRIPT ]; then
+ # If not installed with Homebrew, manually remove package
+ sudo -S sh $SCALAR_UNINSTALL_SCRIPT || echo "warning: Scalar.NET uninstall completed with code $?"
+ echo "Scalar.NET uninstalled!"
+ else
+ echo "warning: Scalar.NET uninstall script not found"
+ fi
+
+ # Re-create the Scalar symlink, in case it was removed by the Scalar.NET uninstall operation
+ mkdir -p $INSTALL_DST/bin
+ /bin/ln -Fs "$SCALAR_C_CMD" "$INSTALL_DST/bin/scalar"
+}
+
+# Run Scalar cleanup (will exit if not applicable)
+cleanupScalar
+
+exit 0
\ No newline at end of file
diff --git a/.github/macos-installer/assets/uninstall.sh b/.github/macos-installer/assets/uninstall.sh
new file mode 100755
index 00000000000000..4fc79fbaa2e652
--- /dev/null
+++ b/.github/macos-installer/assets/uninstall.sh
@@ -0,0 +1,34 @@
+#!/bin/bash -e
+if [ ! -r "/usr/local/git" ]; then
+ echo "Git doesn't appear to be installed via this installer. Aborting"
+ exit 1
+fi
+
+if [ "$1" != "--yes" ]; then
+ echo "This will uninstall git by removing /usr/local/git/, and symlinks"
+ printf "Type 'yes' if you are sure you wish to continue: "
+ read response
+else
+ response="yes"
+fi
+
+if [ "$response" == "yes" ]; then
+ # remove all of the symlinks we've created
+ pkgutil --files com.git.pkg | grep bin | while read f; do
+ if [ -L /usr/local/$f ]; then
+ sudo rm /usr/local/$f
+ fi
+ done
+
+ # forget receipts.
+ pkgutil --packages | grep com.git.pkg | xargs -I {} sudo pkgutil --forget {}
+ echo "Uninstalled"
+
+ # The guts all go here.
+ sudo rm -rf /usr/local/git/
+else
+ echo "Aborted"
+ exit 1
+fi
+
+exit 0
diff --git a/.github/macos-installer/entitlements.xml b/.github/macos-installer/entitlements.xml
new file mode 100644
index 00000000000000..46f675661149b6
--- /dev/null
+++ b/.github/macos-installer/entitlements.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.cs.allow-unsigned-executable-memory
+
+ com.apple.security.cs.disable-library-validation
+
+
+
diff --git a/.github/scripts/codesign.sh b/.github/scripts/codesign.sh
new file mode 100755
index 00000000000000..076b29f93be45e
--- /dev/null
+++ b/.github/scripts/codesign.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+sign_directory () {
+ (
+ cd "$1"
+ for f in *
+ do
+ macho=$(file --mime $f | grep mach)
+ # Runtime sign dylibs and Mach-O binaries
+ if [[ $f == *.dylib ]] || [ ! -z "$macho" ];
+ then
+ echo "Runtime Signing $f"
+ codesign -s "$IDENTITY" $f --timestamp --force --options=runtime --entitlements $ENTITLEMENTS_FILE
+ elif [ -d "$f" ];
+ then
+ echo "Signing files in subdirectory $f"
+ sign_directory "$f"
+
+ else
+ echo "Signing $f"
+ codesign -s "$IDENTITY" $f --timestamp --force
+ fi
+ done
+ )
+}
+
+for i in "$@"
+do
+case "$i" in
+ --payload=*)
+ SIGN_DIR="${i#*=}"
+ shift # past argument=value
+ ;;
+ --identity=*)
+ IDENTITY="${i#*=}"
+ shift # past argument=value
+ ;;
+ --entitlements=*)
+ ENTITLEMENTS_FILE="${i#*=}"
+ shift # past argument=value
+ ;;
+ *)
+ die "unknown option '$i'"
+ ;;
+esac
+done
+
+if [ -z "$SIGN_DIR" ]; then
+ echo "error: missing directory argument"
+ exit 1
+elif [ -z "$IDENTITY" ]; then
+ echo "error: missing signing identity argument"
+ exit 1
+elif [ -z "$ENTITLEMENTS_FILE" ]; then
+ echo "error: missing entitlements file argument"
+ exit 1
+fi
+
+echo "======== INPUTS ========"
+echo "Directory: $SIGN_DIR"
+echo "Signing identity: $IDENTITY"
+echo "Entitlements: $ENTITLEMENTS_FILE"
+echo "======== END INPUTS ========"
+
+sign_directory "$SIGN_DIR"
diff --git a/.github/scripts/notarize.sh b/.github/scripts/notarize.sh
new file mode 100755
index 00000000000000..9315d688afbd49
--- /dev/null
+++ b/.github/scripts/notarize.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+for i in "$@"
+do
+case "$i" in
+ --package=*)
+ PACKAGE="${i#*=}"
+ shift # past argument=value
+ ;;
+ --keychain-profile=*)
+ KEYCHAIN_PROFILE="${i#*=}"
+ shift # past argument=value
+ ;;
+ *)
+ die "unknown option '$i'"
+ ;;
+esac
+done
+
+if [ -z "$PACKAGE" ]; then
+ echo "error: missing package argument"
+ exit 1
+elif [ -z "$KEYCHAIN_PROFILE" ]; then
+ echo "error: missing keychain profile argument"
+ exit 1
+fi
+
+# Exit as soon as any line fails
+set -e
+
+# Send the notarization request
+xcrun notarytool submit -v "$PACKAGE" -p "$KEYCHAIN_PROFILE" --wait
+
+# Staple the notarization ticket (to allow offline installation)
+xcrun stapler staple -v "$PACKAGE"
diff --git a/.github/scripts/symlink-git-hardlinks.rb b/.github/scripts/symlink-git-hardlinks.rb
new file mode 100644
index 00000000000000..174802ccc85d93
--- /dev/null
+++ b/.github/scripts/symlink-git-hardlinks.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+
+install_prefix = ARGV[0]
+puts install_prefix
+git_binary = File.join(install_prefix, '/usr/local/git/bin/git')
+
+[
+ ['git' , File.join(install_prefix, '/usr/local/git/bin')],
+ ['../../bin/git', File.join(install_prefix, '/usr/local/git/libexec/git-core')]
+].each do |link, path|
+ Dir.glob(File.join(path, '*')).each do |file|
+ next if file == git_binary
+ puts "#{file} #{File.size(file)} == #{File.size(git_binary)}"
+ next unless File.size(file) == File.size(git_binary)
+ puts "Symlinking #{file}"
+ puts `ln -sf #{link} #{file}`
+ exit $?.exitstatus if $?.exitstatus != 0
+ end
+end
\ No newline at end of file
diff --git a/.github/workflows/build-git-installers.yml b/.github/workflows/build-git-installers.yml
index 13496b451bf2f1..8dec1303019da4 100644
--- a/.github/workflows/build-git-installers.yml
+++ b/.github/workflows/build-git-installers.yml
@@ -291,3 +291,169 @@ jobs:
name: win-${{matrix.artifact.name}}-x86_64
path: artifacts
# End build Windows installers
+
+ # Build and sign Mac OSX installers & upload artifacts
+ create-macos-artifacts:
+ strategy:
+ matrix:
+ arch:
+ - name: arm64
+ runner: macos-latest-xl-arm64
+ runs-on: ${{ matrix.arch.runner }}
+ needs: prereqs
+ env:
+ VERSION: "${{ needs.prereqs.outputs.tag_version }}"
+ environment: release
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v4
+ with:
+ path: 'git'
+
+ - name: Install Git dependencies
+ run: |
+ set -ex
+
+ # Install x86_64 packages
+ arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+ arch -x86_64 /usr/local/bin/brew install gettext
+
+ # Install arm64 packages
+ brew install automake asciidoc xmlto docbook
+ brew link --force gettext
+
+ # Make universal gettext library
+ lipo -create -output libintl.a /usr/local/opt/gettext/lib/libintl.a /opt/homebrew/opt/gettext/lib/libintl.a
+
+ - name: Set up signing/notarization infrastructure
+ env:
+ A1: ${{ secrets.APPLICATION_CERTIFICATE_BASE64 }}
+ A2: ${{ secrets.APPLICATION_CERTIFICATE_PASSWORD }}
+ I1: ${{ secrets.INSTALLER_CERTIFICATE_BASE64 }}
+ I2: ${{ secrets.INSTALLER_CERTIFICATE_PASSWORD }}
+ N1: ${{ secrets.APPLE_TEAM_ID }}
+ N2: ${{ secrets.APPLE_DEVELOPER_ID }}
+ N3: ${{ secrets.APPLE_DEVELOPER_PASSWORD }}
+ N4: ${{ secrets.APPLE_KEYCHAIN_PROFILE }}
+ run: |
+ echo "Setting up signing certificates"
+ security create-keychain -p pwd $RUNNER_TEMP/buildagent.keychain
+ security default-keychain -s $RUNNER_TEMP/buildagent.keychain
+ security unlock-keychain -p pwd $RUNNER_TEMP/buildagent.keychain
+ # Prevent re-locking
+ security set-keychain-settings $RUNNER_TEMP/buildagent.keychain
+
+ echo "$A1" | base64 -D > $RUNNER_TEMP/cert.p12
+ security import $RUNNER_TEMP/cert.p12 \
+ -k $RUNNER_TEMP/buildagent.keychain \
+ -P "$A2" \
+ -T /usr/bin/codesign
+ security set-key-partition-list \
+ -S apple-tool:,apple:,codesign: \
+ -s -k pwd \
+ $RUNNER_TEMP/buildagent.keychain
+
+ echo "$I1" | base64 -D > $RUNNER_TEMP/cert.p12
+ security import $RUNNER_TEMP/cert.p12 \
+ -k $RUNNER_TEMP/buildagent.keychain \
+ -P "$I2" \
+ -T /usr/bin/pkgbuild
+ security set-key-partition-list \
+ -S apple-tool:,apple:,pkgbuild: \
+ -s -k pwd \
+ $RUNNER_TEMP/buildagent.keychain
+
+ echo "Setting up notarytool"
+ xcrun notarytool store-credentials \
+ --team-id "$N1" \
+ --apple-id "$N2" \
+ --password "$N3" \
+ "$N4"
+
+ - name: Build, sign, and notarize artifacts
+ env:
+ A3: ${{ secrets.APPLE_APPLICATION_SIGNING_IDENTITY }}
+ I3: ${{ secrets.APPLE_INSTALLER_SIGNING_IDENTITY }}
+ N4: ${{ secrets.APPLE_KEYCHAIN_PROFILE }}
+ run: |
+ die () {
+ echo "$*" >&2
+ exit 1
+ }
+
+ # Trace execution, stop on error
+ set -ex
+
+ # Write to "version" file to force match with trigger payload version
+ echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version
+
+ # Configure universal build
+ cat >git/config.mak <>git/config.mak <>git/config.mak <>git/config.mak
+
+ # To make use of the catalogs...
+ export XML_CATALOG_FILES=$homebrew_prefix/etc/xml/catalog
+
+ make -C git -j$(sysctl -n hw.physicalcpu) GIT-VERSION-FILE dist dist-doc
+
+ # Extract tarballs
+ mkdir payload manpages
+ tar -xvf git/git-$VERSION.tar.gz -C payload
+ tar -xvf git/git-manpages-$VERSION.tar.gz -C manpages
+
+ # Lay out payload
+ cp git/config.mak payload/git-$VERSION/config.mak
+ make -C git/.github/macos-installer V=1 payload
+
+ # Codesign payload
+ cp -R stage/git-universal-$VERSION/ \
+ git/.github/macos-installer/build-artifacts
+ make -C git/.github/macos-installer V=1 codesign \
+ APPLE_APP_IDENTITY="$A3" || die "Creating signed payload failed"
+
+ # Build and sign pkg
+ make -C git/.github/macos-installer V=1 pkg \
+ APPLE_INSTALLER_IDENTITY="$I3" \
+ || die "Creating signed pkg failed"
+
+ # Notarize pkg
+ make -C git/.github/macos-installer V=1 notarize \
+ APPLE_INSTALLER_IDENTITY="$I3" APPLE_KEYCHAIN_PROFILE="$N4" \
+ || die "Creating signed and notarized pkg failed"
+
+ # Create DMG
+ make -C git/.github/macos-installer V=1 image || die "Creating DMG failed"
+
+ # Move all artifacts into top-level directory
+ mv git/.github/macos-installer/disk-image/*.pkg git/.github/macos-installer/
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: macos-artifacts
+ path: |
+ git/.github/macos-installer/*.dmg
+ git/.github/macos-installer/*.pkg
+ # End build and sign Mac OSX installers