Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions contrib/sourcegraph/packaging/Dockerfile.linux
Original file line number Diff line number Diff line change
@@ -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"]
105 changes: 105 additions & 0 deletions contrib/sourcegraph/packaging/README.md
Original file line number Diff line number Diff line change
@@ -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.
102 changes: 102 additions & 0 deletions contrib/sourcegraph/packaging/build-darwin.sh
Original file line number Diff line number Diff line change
@@ -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 <zlib.h>\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"
)
107 changes: 107 additions & 0 deletions contrib/sourcegraph/packaging/build-from-source.sh
Original file line number Diff line number Diff line change
@@ -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"
46 changes: 46 additions & 0 deletions contrib/sourcegraph/packaging/build-linux.sh
Original file line number Diff line number Diff line change
@@ -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"
Loading
Loading