From 289584729c5a85f5e7224321a6924000bf62df87 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Fri, 16 Jul 2021 10:35:04 -0400 Subject: [PATCH 1/6] release: create initial Windows installer build workflow - trigger on tag matching basic "vfs" version pattern - validate tag is annotated & matches stricter checks - include `scalar` - build x86_64 & portable git installers, upload artifacts to workflow Update Apr 18, 2022: these steps are built explicitly on 'windows-2019' agents (rather than 'windows-latest') to ensure the correct version of Visual Studio is used (verified in the pipeline via 'type -p mspdb140.dll'). Additionally, due to a known (but not-yet-fixed) issue downloading the 'build-installers' flavor of the Git for Windows SDK with the 'git-for-windows/setup-git-for-windows-sdk' Action, the SDK used is the 'full' flavor. --- .github/workflows/build-git-installers.yml | 286 +++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 .github/workflows/build-git-installers.yml diff --git a/.github/workflows/build-git-installers.yml b/.github/workflows/build-git-installers.yml new file mode 100644 index 0000000000..ffb7f0bcb3 --- /dev/null +++ b/.github/workflows/build-git-installers.yml @@ -0,0 +1,286 @@ +name: build-git-installers + +on: + push: + tags: + - 'v[0-9]*vfs*' # matches "vvfs" + +jobs: + # Check prerequisites for the workflow + prereqs: + runs-on: ubuntu-latest + env: + AZ_SUB: ${{ secrets.AZURE_SUBSCRIPTION }} + AZ_CREDS: ${{ secrets.AZURE_CREDENTIALS }} + outputs: + tag_name: ${{ steps.tag.outputs.name }} # The full name of the tag, e.g. v2.32.0.vfs.0.0 + tag_version: ${{ steps.tag.outputs.version }} # The version number (without preceding "v"), e.g. 2.32.0.vfs.0.0 + steps: + - name: Determine tag to build + run: | + echo "name=${GITHUB_REF#refs/tags/}" >>$GITHUB_OUTPUT + echo "version=${GITHUB_REF#refs/tags/v}" >>$GITHUB_OUTPUT + id: tag + - name: Clone git + uses: actions/checkout@v3 + - name: Validate the tag identified with trigger + run: | + die () { + echo "::error::$*" >&2 + exit 1 + } + + # `actions/checkout` only downloads the peeled tag (i.e. the commit) + git fetch origin +$GITHUB_REF:$GITHUB_REF + + # Verify that the tag is annotated + test $(git cat-file -t "$GITHUB_REF") == "tag" || die "Tag ${{ steps.tag.outputs.name }} is not annotated" + + # Verify tag follows rules in GIT-VERSION-GEN (i.e., matches the specified "DEF_VER" in + # GIT-VERSION-FILE) and matches tag determined from trigger + make GIT-VERSION-FILE + test "${{ steps.tag.outputs.version }}" == "$(sed -n 's/^GIT_VERSION = //p'< GIT-VERSION-FILE)" || die "GIT-VERSION-FILE tag does not match ${{ steps.tag.outputs.name }}" + # End check prerequisites for the workflow + + # Build Windows installers (x86_64 installer & portable) + windows_pkg: + runs-on: windows-2019 + needs: prereqs + env: + GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" + HOME: "${{github.workspace}}\\home" + USERPROFILE: "${{github.workspace}}\\home" + steps: + - name: Configure user + shell: bash + run: + USER_NAME="${{github.actor}}" && + USER_EMAIL="${{github.actor}}@users.noreply.github.com" && + mkdir -p "$HOME" && + git config --global user.name "$USER_NAME" && + git config --global user.email "$USER_EMAIL" && + echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV + - uses: git-for-windows/setup-git-for-windows-sdk@v1 + with: + flavor: build-installers + - name: Clone build-extra + shell: bash + run: | + git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra + - name: Clone git + shell: bash + run: | + # Since we cannot directly clone a specified tag (as we would a branch with `git clone -b `), + # this clone has to be done manually (via init->fetch->reset). + + tag_name="${{ needs.prereqs.outputs.tag_name }}" && + git -c init.defaultBranch=main init && + git remote add -f origin https://github.com/git-for-windows/git && + git fetch "https://github.com/${{github.repository}}" refs/tags/${tag_name}:refs/tags/${tag_name} && + git reset --hard ${tag_name} + - name: Prepare home directory for code-signing + env: + CODESIGN_P12: ${{secrets.CODESIGN_P12}} + CODESIGN_PASS: ${{secrets.CODESIGN_PASS}} + if: env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' + shell: bash + run: | + cd home && + mkdir -p .sig && + echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >.sig/codesign.p12 && + echo -n "$CODESIGN_PASS" >.sig/codesign.pass + git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' + - name: Prepare home directory for GPG signing + if: env.GPGKEY != '' + shell: bash + run: | + # This section ensures that the identity for the GPG key matches the git user identity, otherwise + # signing will fail + + echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import && + info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" && + git config --global user.name "${info% <*}" && + git config --global user.email "<${info#*<}" + env: + GPGKEY: ${{secrets.GPGKEY}} + - name: Build mingw-w64-x86_64-git + env: + GPGKEY: "${{secrets.GPGKEY}}" + shell: bash + run: | + set -x + + # Make sure that there is a `/usr/bin/git` that can be used by `makepkg-mingw` + printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "$@"\n' >/usr/bin/git && + + # Restrict `PATH` to MSYS2 and to Visual Studio (to let `cv2pdb` find the relevant DLLs) + PATH="/mingw64/bin:/usr/bin:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64:/C/Windows/system32" + + type -p mspdb140.dll || exit 1 + + sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-64-bit --build-src-pkg -o artifacts HEAD && + if test -n "$GPGKEY" + then + for tar in artifacts/*.tar* + do + /usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor $tar + done + fi && + + b=$PWD/artifacts && + version=${{ needs.prereqs.outputs.tag_name }} && + (cd /usr/src/MINGW-packages/mingw-w64-git && + cp PKGBUILD.$version PKGBUILD && + git commit -s -m "mingw-w64-git: new version ($version)" PKGBUILD && + git bundle create "$b"/MINGW-packages.bundle origin/main..main) + - name: Publish mingw-w64-x86_64-git + uses: actions/upload-artifact@v3 + with: + name: pkg-x86_64 + path: artifacts + windows_artifacts: + runs-on: windows-2019 + needs: [prereqs, windows_pkg] + env: + HOME: "${{github.workspace}}\\home" + strategy: + matrix: + artifact: + - name: installer + fileprefix: Git + - name: portable + fileprefix: PortableGit + fail-fast: false + steps: + - name: Download pkg-x86_64 + uses: actions/download-artifact@v3 + with: + name: pkg-x86_64 + path: pkg-x86_64 + - uses: git-for-windows/setup-git-for-windows-sdk@v1 + with: + flavor: build-installers + - name: Clone build-extra + shell: bash + run: | + git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra + - name: Prepare home directory for code-signing + env: + CODESIGN_P12: ${{secrets.CODESIGN_P12}} + CODESIGN_PASS: ${{secrets.CODESIGN_PASS}} + if: env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' + shell: bash + run: | + mkdir -p home/.sig && + echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >home/.sig/codesign.p12 && + echo -n "$CODESIGN_PASS" >home/.sig/codesign.pass && + git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' + - name: Retarget auto-update to microsoft/git + shell: bash + run: | + set -x + + b=/usr/src/build-extra && + + filename=$b/git-update-git-for-windows.config + tr % '\t' >$filename <<-\EOF && + [update] + %fromFork = microsoft/git + EOF + + sed -i -e '/^#include "file-list.iss"/a\ + Source: {#SourcePath}\\..\\git-update-git-for-windows.config; DestDir: {app}\\mingw64\\bin; Flags: replacesameversion; AfterInstall: DeleteFromVirtualStore' \ + -e '/^Type: dirifempty; Name: {app}\\{#MINGW_BITNESS}$/i\ + Type: files; Name: {app}\\{#MINGW_BITNESS}\\bin\\git-update-git-for-windows.config\ + Type: dirifempty; Name: {app}\\{#MINGW_BITNESS}\\bin' \ + $b/installer/install.iss + - name: Set the installer Publisher to the Git Fundamentals team + shell: bash + run: | + b=/usr/src/build-extra && + sed -i -e 's/^\(AppPublisher=\).*/\1The Git Fundamentals Team at GitHub/' $b/installer/install.iss + - name: Let the installer configure Visual Studio to use the installed Git + shell: bash + run: | + set -x + + b=/usr/src/build-extra && + + sed -i -e '/^ *InstallAutoUpdater();$/a\ + CustomPostInstall();' \ + -e '/^ *UninstallAutoUpdater();$/a\ + CustomPostUninstall();' \ + $b/installer/install.iss && + + cat >>$b/installer/helpers.inc.iss <<\EOF + + procedure CustomPostInstall(); + begin + if not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\15.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\16.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\17.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\18.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\19.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\20.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) then + LogError('Could not register TeamFoundation\GitSourceControl'); + end; + + procedure CustomPostUninstall(); + begin + if not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\15.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\16.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\17.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\18.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\19.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\20.0\TeamFoundation\GitSourceControl','GitPath') then + LogError('Could not register TeamFoundation\GitSourceControl'); + end; + EOF + - name: Enable Scalar/C and the auto-updater in the installer by default + shell: bash + run: | + set -x + + b=/usr/src/build-extra && + + sed -i -e "/ChosenOptions:=''/a\\ + if (ExpandConstant('{param:components|/}')='/') then begin\n\ + WizardSelectComponents('autoupdate');\n\ + #ifdef WITH_SCALAR\n\ + WizardSelectComponents('scalar');\n\ + #endif\n\ + end;" $b/installer/install.iss + - name: Build 64-bit ${{matrix.artifact.name}} + shell: bash + run: | + set -x + + # Copy the PDB archive to the directory where `--include-pdbs` expects it + b=/usr/src/build-extra && + mkdir -p $b/cached-source-packages && + cp pkg-x86_64/*-pdb* $b/cached-source-packages/ && + + # Build the installer, embedding PDBs + eval $b/please.sh make_installers_from_mingw_w64_git --include-pdbs \ + --version=${{ needs.prereqs.outputs.tag_version }} \ + -o artifacts --${{matrix.artifact.name}} \ + --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz \ + --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && + + if test portable = '${{matrix.artifact.name}}' && test -n "$(git config alias.signtool)" + then + git signtool artifacts/PortableGit-*.exe + fi && + openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.exe | sed "s/.* //" >artifacts/sha-256.txt + - name: Verify that .exe files are code-signed + if: env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' + shell: bash + run: | + PATH=$PATH:"/c/Program Files (x86)/Windows Kits/10/App Certification Kit/" \ + signtool verify //pa artifacts/${{matrix.artifact.fileprefix}}-*.exe + - name: Publish ${{matrix.artifact.name}}-x86_64 + uses: actions/upload-artifact@v3 + with: + name: win-${{matrix.artifact.name}}-x86_64 + path: artifacts + # End build Windows installers From ee69abb1e0679edbdeb612fa7250d69bad3d06b1 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Fri, 16 Jul 2021 10:38:13 -0400 Subject: [PATCH 2/6] release: add Mac OSX installer build - include `scalar` - build signed .dmg & .pkg for target OS version 10.6 - upload artifacts to workflow Update 2022-08-11: .dmg and .pkg are now signed --- .github/macos-installer/Makefile | 116 ++++++++ .../assets/etc/gitconfig.osxkeychain | 2 + .../assets/git-components.plist | 18 ++ .../assets/scripts/postinstall | 62 ++++ .github/macos-installer/assets/uninstall.sh | 34 +++ .github/scripts/run-esrp-signing.py | 135 +++++++++ .github/scripts/set-up-esrp.ps1 | 12 + .github/scripts/symlink-git-hardlinks.rb | 19 ++ .github/workflows/build-git-installers.yml | 274 ++++++++++++++++++ 9 files changed, 672 insertions(+) create mode 100644 .github/macos-installer/Makefile create mode 100644 .github/macos-installer/assets/etc/gitconfig.osxkeychain create mode 100644 .github/macos-installer/assets/git-components.plist create mode 100755 .github/macos-installer/assets/scripts/postinstall create mode 100755 .github/macos-installer/assets/uninstall.sh create mode 100644 .github/scripts/run-esrp-signing.py create mode 100644 .github/scripts/set-up-esrp.ps1 create mode 100644 .github/scripts/symlink-git-hardlinks.rb diff --git a/.github/macos-installer/Makefile b/.github/macos-installer/Makefile new file mode 100644 index 0000000000..39837650ae --- /dev/null +++ b/.github/macos-installer/Makefile @@ -0,0 +1,116 @@ +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) + +ARCH := x86_64 +ARCH_CODE := x86_64 +ARCH_FLAGS_x86_64 := -arch x86_64 + +CFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS_${ARCH_CODE}) +LDFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS_${ARCH_CODE}) + +PREFIX := /usr/local +GIT_PREFIX := $(PREFIX)/git + +BUILD_CODE := intel-$(ARCH_CODE) +BUILD_DIR := $(GITHUB_WORKSPACE)/payload +DESTDIR := $(PWD)/stage/git-$(BUILD_CODE)-$(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}'") + +.PHONY: image pkg payload + +.SECONDARY: + +$(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(BUILD_CODE): + 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 + 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)-$(BUILD_CODE) $(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_CODE): $(BUILD_DIR)/git-$(VERSION)/osx-built +ifeq ("$(ARCH_CODE)", "universal") + File $(BUILD_DIR)/git-$(VERSION)/git + File $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain +else + [ "$$(File $(BUILD_DIR)/git-$(VERSION)/git | cut -f 5 -d' ')" == "$(ARCH_CODE)" ] + [ "$$(File $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain | cut -f 5 -d' ')" == "$(ARCH_CODE)" ] +endif + touch $@ + +disk-image/VERSION-$(VERSION)-$(ARCH_CODE): + rm -f disk-image/*.pkg disk-image/VERSION-* disk-image/.DS_Store + mkdir disk-image + touch "$@" + +disk-image/git-$(VERSION)-$(BUILD_CODE).pkg: disk-image/VERSION-$(VERSION)-$(ARCH_CODE) symlinks + pkgbuild --identifier com.git.pkg --version $(VERSION) --root $(ARTIFACTDIR)$(PREFIX) --scripts assets/scripts --install-location $(PREFIX) --component-plist ./assets/git-components.plist disk-image/git-$(VERSION)-$(BUILD_CODE).pkg + +git-%-$(BUILD_CODE).dmg: + hdiutil create git-$(VERSION)-$(BUILD_CODE).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) Intel $(ARCH)" -ov + hdiutil convert -format UDZO -o $@ git-$(VERSION)-$(BUILD_CODE).uncompressed.dmg + rm -f git-$(VERSION)-$(BUILD_CODE).uncompressed.dmg + +payload: $(BUILD_DIR)/git-$(VERSION)/osx-installed $(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_CODE) + +pkg: disk-image/git-$(VERSION)-$(BUILD_CODE).pkg + +image: git-$(VERSION)-$(BUILD_CODE).dmg diff --git a/.github/macos-installer/assets/etc/gitconfig.osxkeychain b/.github/macos-installer/assets/etc/gitconfig.osxkeychain new file mode 100644 index 0000000000..788266b3a4 --- /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 0000000000..78db36777d --- /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 0000000000..94056db9b7 --- /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 0000000000..4fc79fbaa2 --- /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/scripts/run-esrp-signing.py b/.github/scripts/run-esrp-signing.py new file mode 100644 index 0000000000..725bf4580f --- /dev/null +++ b/.github/scripts/run-esrp-signing.py @@ -0,0 +1,135 @@ +import argparse +import json +import os +import glob +import pprint +import subprocess +import sys +import re + +parser = argparse.ArgumentParser(description='Sign binaries for macOS') +parser.add_argument('path', help='Path to file for signing') +parser.add_argument('keycode', help='Platform-specific key code for signing') +parser.add_argument('opcode', help='Platform-specific operation code for signing') +# Setting nargs=argparse.REMAINDER allows us to pass in params that begin with `--` +parser.add_argument('--params', nargs=argparse.REMAINDER, help='Parameters for signing') +args = parser.parse_args() + +esrp_tool = os.path.join("esrp", "tools", "EsrpClient.exe") + +aad_id = os.environ['AZURE_AAD_ID'].strip() +workspace = os.environ['GITHUB_WORKSPACE'].strip() + +source_location = args.path +files = glob.glob(os.path.join(source_location, "*")) + +print("Found files:") +pprint.pp(files) + +auth_json = { + "Version": "1.0.0", + "AuthenticationType": "AAD_CERT", + "TenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "ClientId": f"{aad_id}", + "AuthCert": { + "SubjectName": f"CN={aad_id}.microsoft.com", + "StoreLocation": "LocalMachine", + "StoreName": "My", + "SendX5c" : "true" + }, + "RequestSigningCert": { + "SubjectName": f"CN={aad_id}", + "StoreLocation": "LocalMachine", + "StoreName": "My" + } +} + +input_json = { + "Version": "1.0.0", + "SignBatches": [ + { + "SourceLocationType": "UNC", + "SourceRootDirectory": source_location, + "DestinationLocationType": "UNC", + "DestinationRootDirectory": workspace, + "SignRequestFiles": [], + "SigningInfo": { + "Operations": [ + { + "KeyCode": f"{args.keycode}", + "OperationCode": f"{args.opcode}", + "Parameters": {}, + "ToolName": "sign", + "ToolVersion": "1.0", + } + ] + } + } + ] +} + +# add files to sign +for f in files: + name = os.path.basename(f) + input_json["SignBatches"][0]["SignRequestFiles"].append( + { + "SourceLocation": name, + "DestinationLocation": os.path.join("signed", name), + } + ) + +# add parameters to input.json (e.g. enabling the hardened runtime for macOS) +if args.params is not None: + i = 0 + while i < len(args.params): + input_json["SignBatches"][0]["SigningInfo"]["Operations"][0]["Parameters"][args.params[i]] = args.params[i + 1] + i += 2 + +policy_json = { + "Version": "1.0.0", + "Intent": "production release", + "ContentType": "binary", +} + +configs = [ + ("auth.json", auth_json), + ("input.json", input_json), + ("policy.json", policy_json), +] + +for filename, data in configs: + with open(filename, 'w') as fp: + json.dump(data, fp) + +# Run ESRP Client +esrp_out = "esrp_out.json" +result = subprocess.run( + [esrp_tool, "sign", + "-a", "auth.json", + "-i", "input.json", + "-p", "policy.json", + "-o", esrp_out, + "-l", "Verbose"], + capture_output=True, + text=True, + cwd=workspace) + +# Scrub log before printing +log = re.sub(r'^.+Uploading.*to\s*destinationUrl\s*(.+?),.+$', + '***', + result.stdout, + flags=re.IGNORECASE|re.MULTILINE) +print(log) + +if result.returncode != 0: + print("Failed to run ESRPClient.exe") + sys.exit(1) + +if os.path.isfile(esrp_out): + print("ESRP output json:") + with open(esrp_out, 'r') as fp: + pprint.pp(json.load(fp)) + +for file in files: + if os.path.isfile(os.path.join("signed", file)): + print(f"Success!\nSigned {file}") \ No newline at end of file diff --git a/.github/scripts/set-up-esrp.ps1 b/.github/scripts/set-up-esrp.ps1 new file mode 100644 index 0000000000..ca56266e33 --- /dev/null +++ b/.github/scripts/set-up-esrp.ps1 @@ -0,0 +1,12 @@ +# Install ESRP client +az storage blob download --file esrp.zip --auth-mode login --account-name esrpsigningstorage --container signing-resources --name microsoft.esrpclient.1.2.76.nupkg +Expand-Archive -Path esrp.zip -DestinationPath .\esrp + +# Install certificates +az keyvault secret download --vault-name "$env:AZURE_VAULT" --name "$env:AUTH_CERT" --file out.pfx +certutil -f -importpfx out.pfx +Remove-Item out.pfx + +az keyvault secret download --vault-name "$env:AZURE_VAULT" --name "$env:REQUEST_SIGNING_CERT" --file out.pfx +certutil -f -importpfx out.pfx +Remove-Item out.pfx \ No newline at end of file diff --git a/.github/scripts/symlink-git-hardlinks.rb b/.github/scripts/symlink-git-hardlinks.rb new file mode 100644 index 0000000000..174802ccc8 --- /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 ffb7f0bcb3..c3f842dbae 100644 --- a/.github/workflows/build-git-installers.yml +++ b/.github/workflows/build-git-installers.yml @@ -284,3 +284,277 @@ jobs: name: win-${{matrix.artifact.name}}-x86_64 path: artifacts # End build Windows installers + + # Build and sign Mac OSX installers & upload artifacts + osx_build: + runs-on: macos-latest + needs: prereqs + env: + # `gettext` is keg-only + LDFLAGS: -L/usr/local/opt/gettext/lib + CFLAGS: -I/usr/local/opt/gettext/include + # To make use of the catalogs... + XML_CATALOG_FILES: /usr/local/etc/xml/catalog + VERSION: "${{ needs.prereqs.outputs.tag_version }}" + steps: + - name: Check out repository + uses: actions/checkout@v3 + with: + path: 'git' + + - name: Install Git dependencies + run: | + set -x + brew install automake asciidoc xmlto docbook + brew link --force gettext + + - name: Build payload + run: | + # Configure the environment + set -x + PATH=/usr/local/bin:$PATH + export CURL_LDFLAGS=$(curl-config --libs) + + # Write to "version" file to force match with trigger payload version + echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version + 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 + make -C git/.github/macos-installer V=1 payload + + # This step is necessary because we cannot use the $VERSION + # environment variable or the tag_version output from the prereqs + # job in the upload-artifact task. + mkdir -p build_artifacts + cp -R stage/git-intel-x86_64-$VERSION/ build_artifacts + + # We keep a list of executable files because their executable bits are + # removed when they are zipped, and we need to re-add. + find build_artifacts -type f -a -perm -u=x >executable-files.txt + + - name: Upload macOS artifacts + uses: actions/upload-artifact@v3 + with: + name: tmp.osx-build + path: | + build_artifacts + + - name: Upload list of executable files + uses: actions/upload-artifact@v3 + with: + name: tmp.executable-files + path: | + executable-files.txt + + osx_sign_payload: + # ESRP service requires signing to run on Windows + runs-on: windows-latest + needs: osx_build + steps: + - name: Check out repository + uses: actions/checkout@v3 + with: + path: 'git' + + - name: Download unsigned build artifiacts + uses: actions/download-artifact@v3 + with: + name: tmp.osx-build + path: build_artifacts + + - name: Zip unsigned build artifacts + shell: pwsh + run: | + Compress-Archive -Path build_artifacts build_artifacts/build_artifacts.zip + cd build_artifacts + Get-ChildItem -Exclude build_artifacts.zip | Remove-Item -Recurse -Force + + - uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Set up ESRP client + shell: pwsh + env: + AZURE_VAULT: ${{ secrets.AZURE_VAULT }} + AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }} + REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }} + run: | + git\.github\scripts\set-up-esrp.ps1 + + - name: Run ESRP client + shell: pwsh + env: + AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }} + APPLE_KEY_CODE: ${{ secrets.APPLE_KEY_CODE }} + APPLE_SIGNING_OP_CODE: ${{ secrets.APPLE_SIGNING_OPERATION_CODE }} + run: | + python git\.github\scripts\run-esrp-signing.py build_artifacts ` + $env:APPLE_KEY_CODE $env:APPLE_SIGNING_OP_CODE ` + --params 'Hardening' '--options=runtime' + + - name: Unzip signed build artifacts + shell: pwsh + run: | + Expand-Archive signed/build_artifacts.zip -DestinationPath signed + Remove-Item signed/build_artifacts.zip + + - name: Upload signed payload + uses: actions/upload-artifact@v3 + with: + name: osx-signed-payload + path: | + signed + + osx_pack: + runs-on: macos-latest + needs: [prereqs, osx_sign_payload] + steps: + - name: Check out repository + uses: actions/checkout@v3 + with: + path: 'git' + + - name: Download signed artifacts + uses: actions/download-artifact@v3 + with: + name: osx-signed-payload + + - name: Download list of executable files + uses: actions/download-artifact@v3 + with: + name: tmp.executable-files + + - name: Build macOS pkg + env: + VERSION: "${{ needs.prereqs.outputs.tag_version }}" + run: | + # Install findutils to use gxargs below + brew install findutils + + # Configure the environment + export CURL_LDFLAGS=$(curl-config --libs) + + # Add executable bits and move build_artifacts into + # the same directory as Makefile (so that executable bits + # will be recognized). + gxargs -r -d '\n' chmod a+x Date: Fri, 16 Jul 2021 10:44:26 -0400 Subject: [PATCH 3/6] release: build unsigned Ubuntu .deb package - include `scalar` - build & upload unsigned .deb package --- .github/workflows/build-git-installers.yml | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/.github/workflows/build-git-installers.yml b/.github/workflows/build-git-installers.yml index c3f842dbae..53042d58b5 100644 --- a/.github/workflows/build-git-installers.yml +++ b/.github/workflows/build-git-installers.yml @@ -558,3 +558,81 @@ jobs: name: osx-dmg path: git/.github/macos-installer/*.dmg # End build and sign Mac OSX installers + + # Build unsigned Ubuntu package + ubuntu_build: + runs-on: ubuntu-20.04 + needs: prereqs + steps: + - name: Install git dependencies + run: | + set -ex + + sudo apt-get update -q + sudo apt-get install -y -q --no-install-recommends gettext libcurl4-gnutls-dev libpcre3-dev asciidoc xmlto + - name: Clone git + uses: actions/checkout@v3 + with: + path: git + - name: Build and package .deb + run: | + set -ex + + die () { + echo "$*" >&2 + exit 1 + } + + echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version + make -C git GIT-VERSION-FILE + + VERSION="${{ needs.prereqs.outputs.tag_version }}" + + ARCH="$(dpkg-architecture -q DEB_HOST_ARCH)" + if test -z "$ARCH"; then + die "Could not determine host architecture!" + fi + + PKGNAME="microsoft-git_$VERSION" + PKGDIR="$(dirname $(pwd))/$PKGNAME" + + rm -rf "$PKGDIR" + mkdir -p "$PKGDIR" + + DESTDIR="$PKGDIR" make -C git -j5 V=1 DEVELOPER=1 \ + USE_LIBPCRE=1 \ + NO_CROSS_DIRECTORY_HARDLINKS=1 \ + ASCIIDOC8=1 ASCIIDOC_NO_ROFF=1 \ + ASCIIDOC='TZ=UTC asciidoc' \ + prefix=/usr/local \ + gitexecdir=/usr/local/lib/git-core \ + libexecdir=/usr/local/lib/git-core \ + htmldir=/usr/local/share/doc/git/html \ + install install-doc install-html + + cd .. + mkdir "$PKGNAME/DEBIAN" + + # Based on https://packages.ubuntu.com/xenial/vcs/git + cat >"$PKGNAME/DEBIAN/control" < + Description: Git client built from the https://github.com/microsoft/git repository, + specialized in supporting monorepo scenarios. Includes the Scalar CLI. + EOF + + dpkg-deb --build "$PKGNAME" + + mkdir $GITHUB_WORKSPACE/artifacts + mv "$PKGNAME.deb" $GITHUB_WORKSPACE/artifacts/ + - name: Publish unsigned .deb package + uses: actions/upload-artifact@v3 + with: + name: deb-package-unsigned + path: artifacts/ + # End build unsigned Ubuntu package From 519b27551e22bf267d147c1ebe62536570ed60ed Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Fri, 16 Jul 2021 10:48:08 -0400 Subject: [PATCH 4/6] release: add signing step for .deb package - sign using Azure-stored certificates & client - sign on Windows agent via python script - job skipped if credentials for accessing certificate aren't present --- .github/workflows/build-git-installers.yml | 48 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-git-installers.yml b/.github/workflows/build-git-installers.yml index 53042d58b5..e6da72b7c4 100644 --- a/.github/workflows/build-git-installers.yml +++ b/.github/workflows/build-git-installers.yml @@ -15,12 +15,16 @@ jobs: outputs: tag_name: ${{ steps.tag.outputs.name }} # The full name of the tag, e.g. v2.32.0.vfs.0.0 tag_version: ${{ steps.tag.outputs.version }} # The version number (without preceding "v"), e.g. 2.32.0.vfs.0.0 + deb_signable: ${{ steps.deb.outputs.signable }} # Whether the credentials needed to sign the .deb package are available steps: - name: Determine tag to build run: | echo "name=${GITHUB_REF#refs/tags/}" >>$GITHUB_OUTPUT echo "version=${GITHUB_REF#refs/tags/v}" >>$GITHUB_OUTPUT id: tag + - name: Determine whether signing certificates are present + run: echo "signable=$([[ $AZ_SUB != '' && $AZ_CREDS != '' ]] && echo 'true' || echo 'false')" >>$GITHUB_OUTPUT + id: deb - name: Clone git uses: actions/checkout@v3 - name: Validate the tag identified with trigger @@ -559,7 +563,7 @@ jobs: path: git/.github/macos-installer/*.dmg # End build and sign Mac OSX installers - # Build unsigned Ubuntu package + # Build & sign Ubuntu package ubuntu_build: runs-on: ubuntu-20.04 needs: prereqs @@ -635,4 +639,44 @@ jobs: with: name: deb-package-unsigned path: artifacts/ - # End build unsigned Ubuntu package + ubuntu_sign-artifacts: + runs-on: windows-latest # Must be run on Windows due to ESRP executable OS compatibility + needs: [ubuntu_build, prereqs] + if: needs.prereqs.outputs.deb_signable == 'true' + env: + ARTIFACTS_DIR: artifacts + steps: + - name: Clone repository + uses: actions/checkout@v3 + with: + path: 'git' + - name: Download unsigned packages + uses: actions/download-artifact@v3 + with: + name: deb-package-unsigned + path: unsigned + - uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + - name: Set up ESRP client + shell: pwsh + env: + AZURE_VAULT: ${{ secrets.AZURE_VAULT }} + AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }} + REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }} + run: | + git\.github\scripts\set-up-esrp.ps1 + - name: Sign package + shell: pwsh + env: + AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }} + LINUX_KEY_CODE: ${{ secrets.LINUX_KEY_CODE }} + LINUX_OP_CODE: ${{ secrets.LINUX_OPERATION_CODE }} + run: | + python git\.github\scripts\run-esrp-signing.py unsigned $env:LINUX_KEY_CODE $env:LINUX_OP_CODE + - name: Upload signed artifact + uses: actions/upload-artifact@v3 + with: + name: deb-package-signed + path: signed + # End build & sign Ubuntu package From 78330296479fbf6986e5e3f8f64dc884a0864177 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Fri, 16 Jul 2021 10:51:02 -0400 Subject: [PATCH 5/6] release: create draft GitHub release with packages & installers - create release & uploads artifact using Octokit - use job "if" condition to handle uploading signed *or* unsigned .deb --- .github/workflows/build-git-installers.yml | 96 ++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/.github/workflows/build-git-installers.yml b/.github/workflows/build-git-installers.yml index e6da72b7c4..1392619d72 100644 --- a/.github/workflows/build-git-installers.yml +++ b/.github/workflows/build-git-installers.yml @@ -680,3 +680,99 @@ jobs: name: deb-package-signed path: signed # End build & sign Ubuntu package + + create-github-release: + runs-on: ubuntu-latest + needs: [prereqs, windows_artifacts, osx_publish_dmg, ubuntu_sign-artifacts] + if: | + success() || + (needs.ubuntu_sign-artifacts.result == 'skipped' && + needs.osx_publish_dmg.result == 'success' && + needs.windows_artifacts.result == 'success') + steps: + - name: Download Windows portable installer + uses: actions/download-artifact@v3 + with: + name: win-portable-x86_64 + path: win-portable-x86_64 + - name: Download Windows x86_64 installer + uses: actions/download-artifact@v3 + with: + name: win-installer-x86_64 + path: win-installer-x86_64 + - name: Download Mac dmg + uses: actions/download-artifact@v3 + with: + name: osx-dmg + path: osx-dmg + - name: Download Mac pkg + uses: actions/download-artifact@v3 + with: + name: osx-signed-pkg + path: osx-pkg + - name: Download Ubuntu package (signed) + if: needs.prereqs.outputs.deb_signable == 'true' + uses: actions/download-artifact@v3 + with: + name: deb-package-signed + path: deb-package + - name: Download Ubuntu package (unsigned) + if: needs.prereqs.outputs.deb_signable != 'true' + uses: actions/download-artifact@v3 + with: + name: deb-package-unsigned + path: deb-package + - uses: actions/github-script@v6 + with: + script: | + const fs = require('fs'); + const path = require('path'); + + var releaseMetadata = { + owner: context.repo.owner, + repo: context.repo.repo + }; + + // Create the release + var tagName = "${{ needs.prereqs.outputs.tag_name }}"; + var createdRelease = await github.rest.repos.createRelease({ + ...releaseMetadata, + draft: true, + tag_name: tagName, + name: tagName + }); + releaseMetadata.release_id = createdRelease.data.id; + + // Uploads contents of directory to the release created above + async function uploadDirectoryToRelease(directory, includeExtensions=[]) { + return fs.promises.readdir(directory) + .then(async(files) => Promise.all( + files.filter(file => { + return includeExtensions.length==0 || includeExtensions.includes(path.extname(file).toLowerCase()); + }) + .map(async (file) => { + var filePath = path.join(directory, file); + github.rest.repos.uploadReleaseAsset({ + ...releaseMetadata, + name: file, + headers: { + "content-length": (await fs.promises.stat(filePath)).size + }, + data: fs.createReadStream(filePath) + }); + })) + ); + } + + await Promise.all([ + // Upload Windows artifacts + uploadDirectoryToRelease('win-installer-x86_64', ['.exe']), + uploadDirectoryToRelease('win-portable-x86_64', ['.exe']), + + // Upload Mac artifacts + uploadDirectoryToRelease('osx-dmg'), + uploadDirectoryToRelease('osx-pkg'), + + // Upload Ubuntu artifacts + uploadDirectoryToRelease('deb-package') + ]); From 72d94517f2d09a8932e72f7f26e16704fdeb3dd3 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Wed, 6 Oct 2021 15:45:07 -0400 Subject: [PATCH 6/6] release: continue pestering until user upgrades In 'git-update-git-for-windows', there is a recently_seen variable that is loaded from Git config. This is intended to allow users to say "No, I don't want that version of Git for Windows." If users say no, then they are not reminded. Ever. We want users of microsoft/git to be notified repeately until they upgrade. The first notification might be dismissed because they don't want to interrupt their work. They should get the picture within a few reminders and upgrade in a timely fashion. Signed-off-by: Derrick Stolee --- .github/workflows/build-git-installers.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build-git-installers.yml b/.github/workflows/build-git-installers.yml index 1392619d72..c1a0708091 100644 --- a/.github/workflows/build-git-installers.yml +++ b/.github/workflows/build-git-installers.yml @@ -198,6 +198,15 @@ jobs: Type: files; Name: {app}\\{#MINGW_BITNESS}\\bin\\git-update-git-for-windows.config\ Type: dirifempty; Name: {app}\\{#MINGW_BITNESS}\\bin' \ $b/installer/install.iss + - name: Set alerts to continue until upgrade is taken + shell: bash + run: | + set -x + + b=/mingw64/bin && + + sed -i -e '6 a use_recently_seen=no' \ + $b/git-update-git-for-windows - name: Set the installer Publisher to the Git Fundamentals team shell: bash run: |