diff --git a/contrib/sourcegraph/packaging/Dockerfile.linux b/contrib/sourcegraph/packaging/Dockerfile.linux new file mode 100644 index 00000000000000..f7e535c80ee932 --- /dev/null +++ b/contrib/sourcegraph/packaging/Dockerfile.linux @@ -0,0 +1,10 @@ +FROM debian:12@sha256:6ebd97fa83deb272194a2cf015b3d26a4d538e9ad3a7a79d544c8af5b0a01443 + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential ca-certificates cargo file gettext libcurl4-openssl-dev \ + libexpat1-dev libpcre2-dev libssl-dev patchelf perl tcl tk zlib1g-dev && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /src +ENTRYPOINT ["contrib/sourcegraph/packaging/build-from-source.sh", "linux-amd64"] diff --git a/contrib/sourcegraph/packaging/README.md b/contrib/sourcegraph/packaging/README.md new file mode 100644 index 00000000000000..fa752c9b8d88ac --- /dev/null +++ b/contrib/sourcegraph/packaging/README.md @@ -0,0 +1,105 @@ +# Sourcegraph Git archives + +These scripts produce full, relocatable Git installations for Sourcegraph +engineer Macs and Amp orbs. They do not change Git behavior. Both builders +export the exact upstream-compatible `v2.55.0` source at commit +`e9019fcafe0040228b8631c30f97ae1adb61bcdc`, regardless of the branch from +which the packaging script runs. + +The intended immutable downstream release is `sourcegraph/v2.55.0-1`. A +release consists of exactly these files: + +* `git-sourcegraph-v2.55.0-1-linux-amd64.tar.gz` +* `git-sourcegraph-v2.55.0-1-linux-amd64.tar.gz.sha256` +* `git-sourcegraph-v2.55.0-1-darwin-arm64.tar.gz` +* `git-sourcegraph-v2.55.0-1-darwin-arm64.tar.gz.sha256` + +Each archive has one `git-sourcegraph/` root. Stripping that directory exposes +`bin/`, `libexec/`, `share/`, optional `lib/`, and `BUILD-INFO`. The latter +records the source tag and commit, downstream version, build host, dependency +versions, recipe commit, and the identity embedded in Git. The source commit is +what was compiled; the recipe commit identifies the packaging implementation. +Consumers should verify the checksum sidecar before extracting. + +The source constants in both entry-point scripts move together. They currently +pin upstream `v2.55.0` because this experiment has no behavior patches. When a +future Sourcegraph behavior patch lands, update the source ref and commit to the +exact downstream revision containing that patch; never leave the builder +exporting an older upstream commit. + +## Linux AMD64 + +Install Docker, then run: + +```console +./contrib/sourcegraph/packaging/build-linux.sh +./contrib/sourcegraph/packaging/validate-linux-archive.sh \ + artifacts/git-sourcegraph-v2.55.0-1-linux-amd64.tar.gz +``` + +The builder image starts from Debian 12 at a pinned multi-platform image +digest. `BUILD-INFO` captures the selected amd64 image's installed package +versions. The archive bundles the non-glibc dynamic dependency closure and +uses relative ELF RPATHs; glibc itself remains at Debian 12's 2.36 baseline. +Installed executables are stripped without removing features. +Git's Rust components remain enabled and are built with Debian's Rust toolchain. +The build container uses the invoking user's numeric UID and GID so bind-mount +contents and resulting artifacts remain owned and removable by that user. +The validator moves the unpacked tree, checks source identity, templates, +PCRE2, user config, `/etc/gitconfig`, HTTPS, and all ELF dependencies. + +## macOS ARM64 + +The Mac artifact must be built and validated on a supported Apple Silicon Mac. +Install Xcode command-line tools, Rust, and GNU tar, then run: + +```console +xcode-select --install # if the tools are not already installed +brew install rust gnu-tar +./contrib/sourcegraph/packaging/build-darwin.sh +``` + +The script discards inherited Nix SDK, compiler, and library search settings; +uses an Apple Xcode SDK; and targets macOS 14 by default. If `xcode-select` +points outside the normal Apple developer directories, the script uses +`/Applications/Xcode.app` when available and otherwise stops before building. +Override Xcode with `SOURCEGRAPH_GIT_DEVELOPER_DIR` or the deployment floor with +`SOURCEGRAPH_GIT_DEPLOYMENT_TARGET` only when deliberately preparing a +different artifact. It downloads checksum-pinned PCRE2 10.48 source and builds +it statically for the same target. Git uses the macOS SDK's curl, iconv, and +system libraries. Localization is disabled because macOS has no system libintl +and linking an incidental Homebrew gettext would make the archive depend on +the build machine. Git still includes its English fallthrough messages. + +The full install includes `git-credential-osxkeychain`, rejects non-system +Mach-O dependencies (including `/opt/homebrew` and build paths), verifies +arm64 and the macOS 14 deployment floor, strips ephemeral source/staging paths, +and then ad-hoc signs unsigned installed binaries. Ad-hoc signatures are not +Apple notarization and do not establish publisher identity. + +Before an experimental service release, unpack the archive into two different +directories and run `bin/git version --build-options`, `bin/git init`, a PCRE2 +`git grep -P`, an HTTPS clone/fetch, and the team's normal SSH, GPG signing, and +Git LFS workflows. Inspect every Mach-O file with `otool -L` and +`codesign --verify --verbose`. Publish the checksummed archives only as an +opt-in prerelease under an immutable downstream tag; sign that tag separately +when signing infrastructure is available. Creating the tag or GitHub release +is intentionally outside these scripts. + +Validation on macOS 26.6.2 exercised those core workflows, but the locked +noninteractive login keychain prevented a `credential-osxkeychain` store/get/ +erase round trip. The macOS 14 deployment floor was inspected in Mach-O load +commands, not run on macOS 14. Complete both checks before describing this as a +fully supported everyday Git replacement. + +## License notices + +Both archives include Git's `COPYING` under `LICENSES/`. Darwin also includes +the pinned PCRE2 source's `LICENCE`. Linux includes Debian's copyright notice +for every package whose shared library is copied into `lib/`, while +`BUNDLED-LIBRARIES` records each library's exact binary and source package +versions and a Debian source-retrieval link. References to Debian's +`/usr/share/common-licenses` resolve within `LICENSES/debian/common-licenses`. +System libraries referenced by the Darwin archive are not redistributed. +Release notes should link the exact Git and PCRE2 sources; checksum sidecars +are checksums, not signatures. diff --git a/contrib/sourcegraph/packaging/build-darwin.sh b/contrib/sourcegraph/packaging/build-darwin.sh new file mode 100755 index 00000000000000..fe51c82efe341f --- /dev/null +++ b/contrib/sourcegraph/packaging/build-darwin.sh @@ -0,0 +1,102 @@ +#!/bin/sh +set -eu + +SOURCE_TAG=v2.55.0 +SOURCE_COMMIT=e9019fcafe0040228b8631c30f97ae1adb61bcdc +RELEASE_VERSION=v2.55.0-1 +PCRE2_VERSION=10.48 +PCRE2_SHA256=b6c68fdf6f3ac31388b50aa89ff0fc49c00c987c16e7b5146491d12003f2c8ed + +test "$(uname -s)" = Darwin && test "$(uname -m)" = arm64 || { + echo 'error: the Darwin archive must be built on an arm64 Mac' >&2 + exit 1 +} + +root=$(git rev-parse --show-toplevel) +output=${1:-"$root/artifacts"} +RECIPE_COMMIT=$(git -C "$root" rev-parse HEAD) +actual=$(git -C "$root" rev-parse "$SOURCE_TAG^{commit}") +test "$actual" = "$SOURCE_COMMIT" || { + echo "error: $SOURCE_TAG resolved to $actual, expected $SOURCE_COMMIT" >&2 + exit 1 +} + +mkdir -p "$output" +output=$(cd "$output" && pwd) +work=$(mktemp -d) +trap 'rm -rf "$work"' EXIT HUP INT TERM + +# Resolve the non-Apple tools before replacing the inherited PATH. Sourcegraph +# shells may export a Nix SDK and library search paths which must not influence +# a redistributable Mac build. +rust_dir=$(dirname "$(command -v rustc)") +cargo_dir=$(dirname "$(command -v cargo)") +gtar_dir=$(dirname "$(command -v gtar)") +unset SDKROOT CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH LIBRARY_PATH \ + LD_LIBRARY_PATH DYLD_LIBRARY_PATH PKG_CONFIG_PATH CFLAGS CPPFLAGS LDFLAGS \ + CC CXX AR RANLIB +if test -n "${SOURCEGRAPH_GIT_DEVELOPER_DIR:-}" +then + DEVELOPER_DIR=$SOURCEGRAPH_GIT_DEVELOPER_DIR +else + selected_developer_dir=$(/usr/bin/xcode-select -p) + case "$selected_developer_dir" in + /Applications/*.app/Contents/Developer|/Library/Developer/CommandLineTools) + DEVELOPER_DIR=$selected_developer_dir ;; + *) + if test -d /Applications/Xcode.app/Contents/Developer + then + DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer + else + echo "error: xcode-select resolved non-Apple developer directory: $selected_developer_dir" >&2 + echo 'set SOURCEGRAPH_GIT_DEVELOPER_DIR to an Apple Xcode or CommandLineTools directory' >&2 + exit 1 + fi ;; + esac +fi +export DEVELOPER_DIR +SDKROOT=$(/usr/bin/xcrun --sdk macosx --show-sdk-path) +export SDKROOT +MACOSX_DEPLOYMENT_TARGET=${SOURCEGRAPH_GIT_DEPLOYMENT_TARGET:-14.0} +export MACOSX_DEPLOYMENT_TARGET +CC=$(/usr/bin/xcrun --find clang) +AR=$(/usr/bin/xcrun --find ar) +RANLIB=$(/usr/bin/xcrun --find ranlib) +export CC AR RANLIB +PATH="$rust_dir:$cargo_dir:$gtar_dir:/usr/bin:/bin:/usr/sbin:/sbin" +export PATH + +# Detect an invalid or incomplete selected SDK before doing the dependency build. +printf '#include \n' | "$CC" -isysroot "$SDKROOT" -x c -fsyntax-only - || { + echo "error: selected Xcode SDK cannot compile against zlib: $SDKROOT" >&2 + exit 1 +} + +git -C "$root" archive "$SOURCE_COMMIT" | tar -x -C "$work" +mkdir -p "$work/contrib/sourcegraph" +cp -R "$root/contrib/sourcegraph/packaging" "$work/contrib/sourcegraph/" + +pcre_archive="$work/pcre2-$PCRE2_VERSION.tar.bz2" +/usr/bin/curl -fL --retry 3 \ + "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$PCRE2_VERSION/pcre2-$PCRE2_VERSION.tar.bz2" \ + -o "$pcre_archive" +printf '%s %s\n' "$PCRE2_SHA256" "$pcre_archive" | /usr/bin/shasum -a 256 -c - +tar -xjf "$pcre_archive" -C "$work" +pcre_prefix="$work/pcre2-install" +( + cd "$work/pcre2-$PCRE2_VERSION" + ./configure --prefix="$pcre_prefix" --disable-shared --enable-static --enable-jit + /usr/bin/make -j"$(getconf _NPROCESSORS_ONLN)" + /usr/bin/make install +) + +( + cd "$work" + SOURCE_DATE_EPOCH=$(git -C "$root" show -s --format=%ct "$SOURCE_COMMIT") \ + SOURCE_COMMIT="$SOURCE_COMMIT" SOURCE_TAG="$SOURCE_TAG" \ + RECIPE_COMMIT="$RECIPE_COMMIT" RELEASE_VERSION="$RELEASE_VERSION" \ + PCRE2_PREFIX="$pcre_prefix" \ + PCRE2_LICENSE="$work/pcre2-$PCRE2_VERSION/LICENCE.md" \ + SOURCE_BUILD_ROOT="$work" \ + contrib/sourcegraph/packaging/build-from-source.sh darwin-arm64 "$output" +) diff --git a/contrib/sourcegraph/packaging/build-from-source.sh b/contrib/sourcegraph/packaging/build-from-source.sh new file mode 100755 index 00000000000000..d04a12b4b14b22 --- /dev/null +++ b/contrib/sourcegraph/packaging/build-from-source.sh @@ -0,0 +1,107 @@ +#!/bin/sh +set -eu + +platform=${1:?usage: build-from-source.sh PLATFORM [OUTPUT]} +output=${2:-/out} +: "${SOURCE_COMMIT:?SOURCE_COMMIT is required}" +: "${SOURCE_TAG:?SOURCE_TAG is required}" +: "${RECIPE_COMMIT:?RECIPE_COMMIT is required}" +: "${RELEASE_VERSION:?RELEASE_VERSION is required}" +: "${SOURCE_DATE_EPOCH:?SOURCE_DATE_EPOCH is required}" + +stage=$(mktemp -d) +trap 'rm -rf "$stage"' EXIT HUP INT TERM + +case "$platform" in + linux-amd64) + test "$(uname -s)-$(uname -m)" = Linux-x86_64 + make_options='RUNTIME_PREFIX=YesPlease USE_LIBPCRE2=YesPlease INSTALL_STRIP=-s NO_INSTALL_HARDLINKS=YesPlease' + ;; + darwin-arm64) + test "$(uname -s)-$(uname -m)" = Darwin-arm64 + # Force the SDK-provided iconv instead of config.mak.uname's Homebrew + # workaround on recent Darwin. Expose only the locally built PCRE2 + # static archive so no package-manager path survives the installation. + pcre_prefix=${PCRE2_PREFIX:?PCRE2_PREFIX is required on Darwin} + test -f "$pcre_prefix/lib/libpcre2-8.a" + static_pcre="$stage/static-pcre2" + mkdir "$static_pcre" + ln -s "$pcre_prefix/include" "$static_pcre/include" + mkdir "$static_pcre/lib" + cp "$pcre_prefix/lib/libpcre2-8.a" "$static_pcre/lib/" + make_options="RUNTIME_PREFIX=YesPlease USE_LIBPCRE2=YesPlease \ + LIBPCREDIR=$static_pcre ICONVDIR=/usr \ + INSTALL_STRIP=-s NO_GETTEXT=YesPlease NO_INSTALL_HARDLINKS=YesPlease \ + USE_HOMEBREW_LIBICONV= NEEDS_GOOD_LIBICONV=" + ;; + *) echo "error: unsupported platform: $platform" >&2; exit 1 ;; +esac + +prefix="$stage/git-sourcegraph" +mkdir -p "$prefix" "$output" + +# Do not let a caller's prior build flags leak into the release artifact. +make clean +# shellcheck disable=SC2086 +make -j"$(getconf _NPROCESSORS_ONLN)" $make_options \ + prefix=/ sysconfdir=/etc GIT_VERSION=2.55.0 \ + GIT_BUILT_FROM_COMMIT="$SOURCE_COMMIT" all +# shellcheck disable=SC2086 +make $make_options prefix=/ sysconfdir=/etc GIT_VERSION=2.55.0 \ + GIT_BUILT_FROM_COMMIT="$SOURCE_COMMIT" DESTDIR="$prefix" install + +mkdir "$prefix/LICENSES" +cp COPYING "$prefix/LICENSES/Git-COPYING" + +if test "$platform" = darwin-arm64 +then + pcre2_license=${PCRE2_LICENSE:?PCRE2_LICENSE is required on Darwin} + test -f "$pcre2_license" || { + echo "error: PCRE2 license notice not found: $pcre2_license" >&2 + exit 1 + } + cp "$pcre2_license" "$prefix/LICENSES/PCRE2-LICENCE" + # The keychain helper is intentionally included in the full Mac install. + # shellcheck disable=SC2086 + make $make_options prefix=/ sysconfdir=/etc GIT_VERSION=2.55.0 \ + GIT_BUILT_FROM_COMMIT="$SOURCE_COMMIT" DESTDIR="$prefix" \ + install-git-credential-osxkeychain + contrib/sourcegraph/packaging/verify-darwin-dependencies.sh "$prefix" +else + contrib/sourcegraph/packaging/bundle-linux-libraries.sh "$prefix" +fi + +{ + echo "release_version=$RELEASE_VERSION" + echo "source_tag=$SOURCE_TAG" + echo "source_commit=$SOURCE_COMMIT" + echo "recipe_commit=$RECIPE_COMMIT" + echo "platform=$platform" + echo "source_date_epoch=$SOURCE_DATE_EPOCH" + echo "git_version=$($prefix/bin/git --version)" + echo "git_build_options=$($prefix/bin/git version --build-options | tr '\n' ';')" + echo "build_uname=$(uname -a)" + echo "cc_version=$(cc --version | head -1)" + echo "rustc_version=$(rustc --version)" + echo "cargo_version=$(cargo --version)" + if command -v dpkg-query >/dev/null 2>&1 + then + echo 'builder_image=debian:12@sha256:6ebd97fa83deb272194a2cf015b3d26a4d538e9ad3a7a79d544c8af5b0a01443' + echo 'build_packages_begin' + dpkg-query -W -f='${Package}=${Version}\n' | LC_ALL=C sort + echo 'build_packages_end' + else + echo "xcode_version=$(xcodebuild -version | tr '\n' ';')" + echo 'pcre2_version=10.48' + echo 'pcre2_source_sha256=b6c68fdf6f3ac31388b50aa89ff0fc49c00c987c16e7b5146491d12003f2c8ed' + echo "macosx_deployment_target=${MACOSX_DEPLOYMENT_TARGET:-unset}" + fi +} >"$prefix/BUILD-INFO" + +archive="git-sourcegraph-${RELEASE_VERSION}-${platform}.tar.gz" +tar_command=tar +test "$platform" != darwin-arm64 || tar_command=${GTAR:-gtar} +COPYFILE_DISABLE=1 TZ=UTC "$tar_command" --sort=name --mtime="@$SOURCE_DATE_EPOCH" \ + --owner=0 --group=0 --numeric-owner -czf "$output/$archive" -C "$stage" git-sourcegraph +(cd "$output" && shasum -a 256 "$archive" >"$archive.sha256") +echo "$output/$archive" diff --git a/contrib/sourcegraph/packaging/build-linux.sh b/contrib/sourcegraph/packaging/build-linux.sh new file mode 100755 index 00000000000000..891cd81b4d823f --- /dev/null +++ b/contrib/sourcegraph/packaging/build-linux.sh @@ -0,0 +1,46 @@ +#!/bin/sh +set -eu + +SOURCE_TAG=v2.55.0 +SOURCE_COMMIT=e9019fcafe0040228b8631c30f97ae1adb61bcdc +RELEASE_VERSION=v2.55.0-1 +IMAGE=git-sourcegraph-linux-builder:v2.55.0-1 + +root=$(git rev-parse --show-toplevel) +output=${1:-"$root/artifacts"} +RECIPE_COMMIT=$(git -C "$root" rev-parse HEAD) +actual=$(git -C "$root" rev-parse "$SOURCE_TAG^{commit}") +test "$actual" = "$SOURCE_COMMIT" || { + echo "error: $SOURCE_TAG resolved to $actual, expected $SOURCE_COMMIT" >&2 + exit 1 +} + +mkdir -p "$output" +output=$(cd "$output" && pwd) +work=$(mktemp -d) +cleanup() { + status=$? + trap - EXIT HUP INT TERM + rm -rf "$work" || : + exit "$status" +} +trap cleanup EXIT HUP INT TERM + +# Export the release source rather than building whichever fork branch happens +# to contain these packaging scripts. +git -C "$root" archive "$SOURCE_COMMIT" | tar -x -C "$work" +mkdir -p "$work/contrib/sourcegraph" +cp -R "$root/contrib/sourcegraph/packaging" "$work/contrib/sourcegraph/" + +docker build -f "$root/contrib/sourcegraph/packaging/Dockerfile.linux" -t "$IMAGE" "$root" +docker run --rm \ + --user "$(id -u):$(id -g)" \ + -e HOME=/tmp \ + -e SOURCE_DATE_EPOCH="$(git -C "$root" show -s --format=%ct "$SOURCE_COMMIT")" \ + -e SOURCE_COMMIT="$SOURCE_COMMIT" \ + -e SOURCE_TAG="$SOURCE_TAG" \ + -e RECIPE_COMMIT="$RECIPE_COMMIT" \ + -e RELEASE_VERSION="$RELEASE_VERSION" \ + -v "$work:/src" \ + -v "$output:/out" \ + "$IMAGE" diff --git a/contrib/sourcegraph/packaging/bundle-linux-libraries.sh b/contrib/sourcegraph/packaging/bundle-linux-libraries.sh new file mode 100755 index 00000000000000..e0c8fa41513169 --- /dev/null +++ b/contrib/sourcegraph/packaging/bundle-linux-libraries.sh @@ -0,0 +1,102 @@ +#!/bin/sh +set -eu + +prefix=${1:?usage: bundle-linux-libraries.sh PREFIX} +mkdir -p "$prefix/lib" +notices="$prefix/LICENSES/debian" +mkdir -p "$notices" +cp -R /usr/share/common-licenses "$notices/common-licenses" +cat >"$notices/README" <<'EOF' +Debian copyright notices in this directory may refer to license texts under +/usr/share/common-licenses. Their archived copies are in common-licenses/. +EOF +manifest="$prefix/BUNDLED-LIBRARIES" +printf 'library\tbinary_package\tbinary_version\tsource_package\tsource_version\tsource_retrieval\tcopyright_notice\n' >"$manifest" + +find_elfs() { + find "$prefix/bin" "$prefix/libexec" -type f -perm -111 -exec file {} + | + sed -n 's/: .*ELF .*//p' +} + +find_owning_package() { + library=$1 + canonical=$(readlink -f "$library") + for candidate in "$library" "$canonical" + do + case "$candidate" in + /lib/*) alternate=/usr$candidate ;; + /usr/lib/*) alternate=${candidate#/usr} ;; + *) alternate= ;; + esac + for path in "$candidate" "$alternate" + do + test -n "$path" || continue + if ownership=$(dpkg-query -S "$path" 2>/dev/null) + then + printf '%s\n' "$ownership" | sed -n '1{s/: \/.*//;p;}' + return 0 + fi + done + done + return 1 +} + +# ldd reports the complete transitive closure. Keep glibc, its loader, and the +# base POSIX libraries on the host so the archive retains Debian 12's glibc +# floor; bundle feature libraries such as curl, OpenSSL, PCRE2, and expat. +find_elfs | while IFS= read -r executable +do + ldd "$executable" +done | awk '/=> \// { print $3 } /^\// { print $1 }' | LC_ALL=C sort -u | +while IFS= read -r library +do + case "$(basename "$library")" in + ld-linux-*|libc.so.*|libdl.so.*|libm.so.*|libpthread.so.*|libresolv.so.*|librt.so.*|libutil.so.*) + continue ;; + esac + library_name=$(basename "$library") + cp -L "$library" "$prefix/lib/$library_name" + + if package_spec=$(find_owning_package "$library") + then + : + else + echo "error: no Debian package owns $library" >&2 + exit 1 + fi + package=${package_spec%%:*} + package_metadata=$(dpkg-query -W \ + -f='${binary:Package}\t${Version}\t${source:Package}\t${source:Version}' \ + "$package_spec") + tab=$(printf '\t') + IFS="$tab" read -r binary_package binary_version source_package source_version <&2 + exit 1 + } + copyright_name="$package.copyright" + cp -L "$copyright_source" "$notices/$copyright_name" + printf '%s\t%s\t%s\t%s\t%s\thttps://snapshot.debian.org/package/%s/\tLICENSES/debian/%s\n' \ + "$library_name" "$binary_package" "$binary_version" \ + "$source_package" "$source_version" "$source_package" \ + "$copyright_name" >>"$manifest" +done + +for library in "$prefix"/lib/* +do + patchelf --set-rpath '$ORIGIN' "$library" +done + +find_elfs | while IFS= read -r executable +do + relative=${executable#"$prefix"/} + case "$relative" in + bin/*) rpath='$ORIGIN/../lib' ;; + libexec/git-core/*) rpath='$ORIGIN/../../lib' ;; + *) echo "error: unknown executable location: $relative" >&2; exit 1 ;; + esac + patchelf --set-rpath "$rpath" "$executable" +done diff --git a/contrib/sourcegraph/packaging/validate-linux-archive.sh b/contrib/sourcegraph/packaging/validate-linux-archive.sh new file mode 100755 index 00000000000000..f97d9b9921c477 --- /dev/null +++ b/contrib/sourcegraph/packaging/validate-linux-archive.sh @@ -0,0 +1,101 @@ +#!/bin/sh +set -eu + +archive=${1:?usage: validate-linux-archive.sh ARCHIVE} +expected_commit=e9019fcafe0040228b8631c30f97ae1adb61bcdc +work=$(mktemp -d) +trap 'rm -rf "$work"' EXIT HUP INT TERM + +roots=$(tar -tzf "$archive" | sed 's,/.*,,' | LC_ALL=C sort -u) +test "$roots" = git-sourcegraph + +for location in first/a second/moved/prefix +do + mkdir -p "$work/$location" + tar -xzf "$archive" -C "$work/$location" --strip-components=1 + git="$work/$location/bin/git" + test -s "$work/$location/LICENSES/Git-COPYING" + test -s "$work/$location/BUNDLED-LIBRARIES" + test "$($git --version)" = 'git version 2.55.0' + $git version --build-options | grep -F "built from commit: $expected_commit" + test "$($git --exec-path)" = "$work/$location/libexec/git-core" + test "$($git --html-path)" = "$work/$location/share/doc/git-doc" + + home="$work/home" + mkdir -p "$home" + HOME="$home" "$git" config --global sourcegraph.archive-test true + test "$(HOME="$home" "$git" config --global --get sourcegraph.archive-test)" = true + GIT_CONFIG_SYSTEM=/dev/null HOME="$home" "$git" init -q "$work/repository" + test -f "$work/repository/.git/hooks/applypatch-msg.sample" + printf 'needle\n' >"$work/repository/content" + GIT_CONFIG_SYSTEM=/dev/null HOME="$home" "$git" -C "$work/repository" add content + GIT_CONFIG_SYSTEM=/dev/null HOME="$home" "$git" -C "$work/repository" grep -P 'n(?=eedle)' + rm -rf "$work/repository" +done + +# Every bundled shared library identifies its exact Debian binary/source +# package, source retrieval location, and included copyright notice. +prefix="$work/second/moved/prefix" +test -s "$prefix/LICENSES/debian/README" +test -s "$prefix/LICENSES/debian/common-licenses/GPL-2" +test -s "$prefix/LICENSES/debian/common-licenses/LGPL-2.1" +tab=$(printf '\t') +tail -n +2 "$prefix/BUNDLED-LIBRARIES" | while IFS="$tab" read -r \ + library binary_package binary_version source_package source_version source_url copyright_notice +do + test -n "$binary_package" && test -n "$binary_version" + test -n "$source_package" && test -n "$source_version" + test "$source_url" = "https://snapshot.debian.org/package/$source_package/" + test -s "$prefix/$copyright_notice" + test -f "$prefix/lib/$library" +done +for library in "$prefix"/lib/* +do + awk -F '\t' -v library="$(basename "$library")" \ + 'NR > 1 && $1 == library { found = 1 } END { exit !found }' \ + "$prefix/BUNDLED-LIBRARIES" +done + +# Exercise HTTPS with the packaged curl/SSL dependency closure. +GIT_CONFIG_SYSTEM=/dev/null HOME="$work/home" \ + "$work/second/moved/prefix/bin/git" ls-remote \ + https://github.com/git/git.git HEAD | grep -E '^[0-9a-f]{40}[[:space:]]+HEAD$' + +# The default remains host /etc/gitconfig; user config and external tools such +# as ssh, gpg, and git-lfs are deliberately discovered from the host PATH. +strings "$work/second/moved/prefix/bin/git" | grep -Fx /etc/gitconfig +test ! -e "$work/second/moved/prefix/etc/gitconfig" +if test -s /etc/gitconfig +then + "$work/second/moved/prefix/bin/git" config --system --show-origin --list | + awk -F '\t' '$1 != "file:/etc/gitconfig" { exit 1 } END { if (NR == 0) exit 1 }' +fi +GIT_CONFIG_NOSYSTEM=1 HOME="$work/home" \ + "$work/second/moved/prefix/bin/git" config --get sourcegraph.archive-test | grep -Fx true +mkdir "$work/isolated-home" +! GIT_CONFIG_NOSYSTEM=1 HOME="$work/isolated-home" \ + "$work/second/moved/prefix/bin/git" config --get commit.gpgsign + +# Dashed external integrations continue to resolve through PATH. This is the +# mechanism used by git-lfs; SSH and signing programs are likewise external. +mkdir "$work/external" +cat >"$work/external/git-lfs" <&2 + exit 1 + fi + readelf -d "$executable" | grep -E 'RPATH|RUNPATH' | grep -F '$ORIGIN' +done + +echo 'Linux archive validation passed.' diff --git a/contrib/sourcegraph/packaging/verify-darwin-dependencies.sh b/contrib/sourcegraph/packaging/verify-darwin-dependencies.sh new file mode 100755 index 00000000000000..259e3be3be33c2 --- /dev/null +++ b/contrib/sourcegraph/packaging/verify-darwin-dependencies.sh @@ -0,0 +1,41 @@ +#!/bin/sh +set -eu + +prefix=${1:?usage: verify-darwin-dependencies.sh PREFIX} +: "${MACOSX_DEPLOYMENT_TARGET:?MACOSX_DEPLOYMENT_TARGET is required}" +: "${SOURCE_BUILD_ROOT:?SOURCE_BUILD_ROOT is required}" +test -s "$prefix/LICENSES/Git-COPYING" +test -s "$prefix/LICENSES/PCRE2-LICENCE" +status_file=$(mktemp) +trap 'rm -f "$status_file"' EXIT HUP INT TERM +find "$prefix/bin" "$prefix/libexec" -type f -perm -111 | while IFS= read -r executable +do + file "$executable" | grep -q 'Mach-O' || continue + file "$executable" | grep -q 'arm64' || { + echo "error: non-arm64 executable: $executable" >&2 + echo failed >>"$status_file" + } + minos=$(otool -l "$executable" | awk \ + '/cmd LC_BUILD_VERSION/ { found = 1; next } found && $1 == "minos" { print $2; exit }') + test "$minos" = "$MACOSX_DEPLOYMENT_TARGET" || { + echo "error: $executable targets macOS $minos, expected $MACOSX_DEPLOYMENT_TARGET" >&2 + echo failed >>"$status_file" + } + for build_path in "$SOURCE_BUILD_ROOT" "$(dirname "$prefix")" + do + if strings "$executable" | grep -F "$build_path" >/dev/null + then + echo "error: build path embedded in $executable: $build_path" >&2 + echo failed >>"$status_file" + fi + done + otool -L "$executable" | tail -n +2 | awk '{ print $1 }' | while IFS= read -r library + do + case "$library" in + /System/Library/*|/usr/lib/*) ;; + *) echo "error: non-system dependency in $executable: $library" >&2; echo failed >>"$status_file" ;; + esac + done + codesign --verify --verbose "$executable" 2>/dev/null || codesign --force --sign - "$executable" +done +test ! -s "$status_file"