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
31 changes: 15 additions & 16 deletions Dockerfile.packaging
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
FROM golang:1.25.9-bookworm
FROM golang:1.25.9-bookworm AS build

RUN apt-get update
RUN apt-get install -y ruby ruby-dev rubygems build-essential
RUN gem install fpm
ENV GOPATH=/tmp/go
# build.sh shells out to fpm to produce the .deb/.rpm packages. fpm is a Ruby
# gem (needs ruby + ruby-dev + a C toolchain), and the rpm target needs
# rpmbuild from the `rpm` package. Everything else build.sh uses (git, tar,
# gcc, bash, ...) already ships in the golang:bookworm base image.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ruby ruby-dev build-essential rpm \
&& rm -rf /var/lib/apt/lists/* \
&& gem install --no-document fpm

RUN apt-get install -y curl
RUN apt-get install -y rsync
RUN apt-get install -y gcc
RUN apt-get install -y g++
RUN apt-get install -y bash
RUN apt-get install -y git
RUN apt-get install -y tar
RUN apt-get install -y rpm

RUN mkdir -p $GOPATH/src/github.com/github/gh-ost
WORKDIR $GOPATH/src/github.com/github/gh-ost
WORKDIR /gh-ost
COPY . .
RUN bash build.sh

# Export-only stage: `docker build --target artifacts --output type=local,dest=...`
# writes just the release assets to the host, no intermediate container needed.
FROM scratch AS artifacts
COPY --from=build /tmp/gh-ost-release/ /
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Please see [Coding gh-ost](doc/coding-ghost.md) for a guide to getting started d

`gh-ost` is a Go project; it is built with Go `1.15` and above. To build on your own, use either:
- [script/build](https://github.com/github/gh-ost/blob/master/script/build) - this is the same build script used by CI hence the authoritative; artifact is `./bin/gh-ost` binary.
- [build.sh](https://github.com/github/gh-ost/blob/master/build.sh) for building `tar.gz` artifacts in `/tmp/gh-ost-release`
- [build.sh](https://github.com/github/gh-ost/blob/master/build.sh) for building the release artifacts (`tar.gz` archives plus `.rpm`/`.deb` packages and a `SHA256SUMS` manifest) in `/tmp/gh-ost-release`

Generally speaking, `master` branch is stable, but only [releases](https://github.com/github/gh-ost/releases) are to be used in production.

Expand Down
62 changes: 39 additions & 23 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,61 @@
RELEASE_VERSION=
buildpath=

# Create a scratch tree to stage the package filesystem for fpm. It lives in the
# system temp dir, not $buildpath, so it never lands among the release artifacts.
function setuptree() {
b=$( mktemp -d $buildpath/gh-ostXXXXXX ) || return 1
b=$( mktemp -d ) || return 1
mkdir -p $b/gh-ost
mkdir -p $b/gh-ost/usr/bin
echo $b
}

function build {
osname=$1
osshort=$2
GOOS=$3
GOARCH=$4
GOOS=$1
GOARCH=$2

if ! go version | egrep -q 'go1\.(1[5-9]|[2-9][0-9]{1})' ; then
echo "go version must be 1.15 or above"
exit 1
fi

echo "Building ${osname}-${GOARCH} binary"
echo "Building ${GOOS}-${GOARCH} binary"
export GOOS
export GOARCH
CGO_ENABLED="${CGO_ENABLED:-0}" go build -ldflags "$ldflags" -o "$buildpath/$target" go/cmd/gh-ost/main.go

if [ $? -ne 0 ]; then
echo "Build failed for ${osname} ${GOARCH}."
echo "Build failed for ${GOOS} ${GOARCH}."
exit 1
fi

(cd $buildpath && tar cfz ./gh-ost-binary-${osshort}-${GOARCH}-${timestamp}.tar.gz $target)
(cd $buildpath && tar cfz ./gh-ost-${GOOS}-${GOARCH}.tar.gz $target)

# build RPM and deb for Linux, x86-64 only
if [ "$GOOS" == "linux" ] && [ "$GOARCH" == "amd64" ] ; then
# build RPM and deb packages for Linux
if [ "$GOOS" == "linux" ] ; then
echo "Creating Distro full packages"
case "$GOARCH" in
amd64) rpm_arch=x86_64 ; deb_arch=amd64 ;;
arm64) rpm_arch=aarch64 ; deb_arch=arm64 ;;
*) rpm_arch=$GOARCH ; deb_arch=$GOARCH ;;
esac
builddir=$(setuptree)
cp $buildpath/$target $builddir/gh-ost/usr/bin
cd $buildpath
fpm -v "${RELEASE_VERSION}" --epoch 1 -f -s dir -n gh-ost -m 'GitHub' --description "GitHub's Online Schema Migrations for MySQL " --url "https://github.com/github/gh-ost" --vendor "GitHub" --license "Apache 2.0" -C $builddir/gh-ost --prefix=/ -t rpm --rpm-rpmbuild-define "_build_id_links none" --rpm-os linux .
fpm -v "${RELEASE_VERSION}" --epoch 1 -f -s dir -n gh-ost -m 'GitHub' --description "GitHub's Online Schema Migrations for MySQL " --url "https://github.com/github/gh-ost" --vendor "GitHub" --license "Apache 2.0" -C $builddir/gh-ost --prefix=/ -t deb --deb-no-default-config-files .

fpm_opts=(
-v "${RELEASE_VERSION}" --epoch 1 -f -s dir -n gh-ost
-m 'GitHub' --description "GitHub's Online Schema Migrations for MySQL "
--url "https://github.com/github/gh-ost" --vendor "GitHub" --license "Apache 2.0"
-C "$builddir/gh-ost" --prefix=/
)
fpm "${fpm_opts[@]}" -t rpm -a "${rpm_arch}" -p "gh-ost.${rpm_arch}.rpm" --rpm-rpmbuild-define "_build_id_links none" --rpm-os linux .
fpm "${fpm_opts[@]}" -t deb -a "${deb_arch}" -p "gh-ost.${deb_arch}.deb" --deb-no-default-config-files .
cd -
fi

# Drop the bare binary so only tarballs and packages are published as release assets
rm -f "$buildpath/$target"
}

main() {
Expand All @@ -60,22 +75,23 @@ main() {

buildpath=/tmp/gh-ost-release
target=gh-ost
timestamp=$(date "+%Y%m%d%H%M%S")
ldflags="-X main.AppVersion=${RELEASE_VERSION} -X main.GitCommit=${GIT_COMMIT}"

mkdir -p ${buildpath}
rm -rf ${buildpath:?}/*
build GNU/Linux linux linux amd64
build GNU/Linux linux linux arm64
build macOS osx darwin amd64
build macOS osx darwin arm64

bin_files=$(find $buildpath/gh-ost* -type f -maxdepth 1)
echo "Binaries found in:"
echo "$bin_files"

build linux amd64
build linux arm64
build darwin amd64
build darwin arm64

# Generate a SHA256SUMS manifest with basenames only, so a downloaded set can be
# verified in place with `sha256sum -c SHA256SUMS` (no absolute build paths leak in).
# The name has no gh-ost prefix, so it self-excludes from the gh-ost* glob below.
echo "Checksums:"
(shasum -a256 $bin_files 2>/dev/null)
( cd "$buildpath" && shasum -a256 gh-ost* | tee SHA256SUMS )

echo "Release assets:"
ls -1 "$buildpath"

echo "Build Success!"
}
Expand Down
19 changes: 13 additions & 6 deletions script/dock
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#!/bin/bash

set -e

# Usage:
# dock <test|packages> [arg]
# dock test: build gh-ost & run unit and integration tests
# docker pkg [target-path]: build gh-ost release packages and copy to target path (default path: /tmp/gh-ost-release)
# dock <test|pkg> [arg]
# dock test: build gh-ost & run unit and integration tests
# dock pkg [target-path]: build gh-ost release packages and write them to
# target-path (default: /tmp/gh-ost-release)

command="$1"

Expand All @@ -14,12 +17,16 @@ case "$command" in
;;
"pkg")
packages_path="${2:-/tmp/gh-ost-release}"
docker_target="gh-ost-packaging"
docker build . -f Dockerfile.packaging -t "${docker_target}" && docker run --rm -it -v "${packages_path}:/tmp/pkg" "${docker_target}:latest" bash -c 'find /tmp/gh-ost-release/ -maxdepth 1 -type f | xargs cp -t /tmp/pkg'
# BuildKit exports the artifacts stage straight to the host; no intermediate
# container, bind mount, or copy step needed. Requires BuildKit (default in
# modern Docker; set DOCKER_BUILDKIT=1 on older daemons).
DOCKER_BUILDKIT=1 docker build . -f Dockerfile.packaging \
--target artifacts --output "type=local,dest=${packages_path}"
echo "packages generated on ${packages_path}:"
ls -l "${packages_path}"
;;
*)
>&2 echo "Usage: dock dock <test|alpine|packages> [arg]"
>&2 echo "Usage: dock <test|pkg> [target-path]"
exit 1
;;
esac
Loading