Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump libgit2 to 1.3.0 and git2go to V33. #557

Closed
wants to merge 3 commits into from
Closed
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
4 changes: 2 additions & 2 deletions .github/actions/run-tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
ARG BASE_VARIANT=bullseye
ARG GO_VERSION=1.17.5
ARG GO_VERSION=1.17.6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change this to match the build image.

Suggested change
ARG GO_VERSION=1.17.6
ARG GO_VERSION=1.17

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @relu. I updated this on the PR that supersedes this.

ARG XX_VERSION=1.1.0

ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2
ARG LIBGIT2_TAG=libgit2-1.1.1-3
ARG LIBGIT2_TAG=libgit2-1.3.0

FROM tonistiigi/xx:${XX_VERSION} AS xx
FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} as libgit2
Expand Down
97 changes: 30 additions & 67 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,55 +1,11 @@
ARG BASE_VARIANT=bullseye
ARG BASE_VARIANT=alpine
ARG GO_VERSION=1.17
ARG XX_VERSION=1.1.0

ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2
ARG LIBGIT2_TAG=libgit2-1.1.1-3
ARG LIBGIT2_TAG=libgit2-1.3.0

FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} as libgit2

FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} as gostable

FROM gostable AS go-linux

FROM go-${TARGETOS} AS build-base-bullseye

# Copy the build utilities
COPY --from=xx / /

# Align golang base image with bookworm.
# TODO: Replace this with a golang bookworm variant, once that is released.
RUN echo "deb http://deb.debian.org/debian bookworm main" > /etc/apt/sources.list.d/bookworm.list \
&& echo "deb-src http://deb.debian.org/debian bookworm main" /etc/apt/sources.list.d/bookworm.list \
&& xx-apt update \
&& xx-apt -t bookworm upgrade -y \
&& xx-apt -t bookworm install -y curl

COPY --from=libgit2 /Makefile /libgit2/

# Install the libgit2 build dependencies
RUN make -C /libgit2 cmake

ARG TARGETPLATFORM
RUN make -C /libgit2 dependencies

FROM build-base-${BASE_VARIANT} as libgit2-bullseye

ARG TARGETPLATFORM

# First build libgit2 statically, this ensures that all its dependencies
# will be statically available as well.
ARG BUILD_SHARED_LIBS=OFF
RUN FLAGS=$(xx-clang --print-cmake-defines) make -C /libgit2 libgit2

# Rebuild libgit2 this time to generate the shared libraries.
ARG BUILD_SHARED_LIBS=ON
RUN FLAGS=$(xx-clang --print-cmake-defines) make -C /libgit2 libgit2
# Logs glibc version used at built time. The final image must be compatible with it.
RUN ldd --version ldd > /libgit2/built-on-glibc-version


FROM libgit2-${BASE_VARIANT} as build
FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build

# Configure workspace
WORKDIR /workspace
Expand All @@ -64,35 +20,42 @@ COPY go.sum go.sum
# Cache modules
RUN go mod download

# Copy source code
COPY main.go main.go
COPY controllers/ controllers/
COPY pkg/ pkg/
COPY internal/ internal/
RUN apk add clang lld pkgconfig ca-certificates

# Build the binary
ENV CGO_ENABLED=1
ARG TARGETPLATFORM

# The dependencies being statically built are: libgit2, libssh2, libssl, libcrypto and libz.
# Others (such as libc, librt, libdl and libpthread) are resolved at run-time.
# To decrease the likelihood of such dependencies being out of sync, the base build image
# should be aligned with the target (i.e. same debian variant).
RUN FLAGS=$(pkg-config --static --libs --cflags libssh2 libgit2 libssl libcrypto zlib openssl) \
RUN xx-apk add --no-cache \
musl-dev gcc lld binutils-gold

# Performance related changes:
# - Use read-only bind instead of copying go source files.
# - Cache go packages.
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg \
export LIBRARY_PATH="/usr/local/$(xx-info triple)/lib:/usr/local/$(xx-info triple)/lib64:${LIBRARY_PATH}" && \
export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig:/usr/local/$(xx-info triple)/lib64/pkgconfig" && \
export FLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2)" && \
CGO_LDFLAGS="${FLAGS} -static" \
xx-go build \
-ldflags "-s -w -extldflags \"/usr/lib/$(xx-info triple)/libssh2.a /usr/lib/$(xx-info triple)/libssl.a /usr/lib/$(xx-info triple)/libcrypto.a /usr/lib/$(xx-info triple)/libz.a -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-allow-shlib-undefined ${FLAGS} -static\"" \
-ldflags "-s -w" \
-tags 'netgo,osusergo,static_build' \
-o source-controller -trimpath main.go;
-o /source-controller -trimpath main.go;

# The target image must aligned with apt sources used for libgit2.
FROM debian:bookworm-slim as controller
# Ensure that the binary was cross-compiled correctly to the target platform.
RUN xx-verify --static /source-controller

ARG TARGETPLATFORM
RUN apt update && apt install -y ca-certificates

# Copy over binary from build
COPY --from=build /workspace/source-controller /usr/local/bin/
COPY --from=libgit2-bullseye /libgit2/built-on-glibc-version /
FROM gcr.io/distroless/static

# Link repo to the GitHub Container Registry image
LABEL org.opencontainers.image.source="https://github.com/fluxcd/source-controller"

ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt

COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=build /source-controller /usr/local/bin/
COPY ATTRIBUTIONS.md /

USER 65534:65534
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ TAG ?= latest

# Base image used to build the Go binary
LIBGIT2_IMG ?= ghcr.io/fluxcd/golang-with-libgit2
LIBGIT2_TAG ?= libgit2-1.1.1-3
LIBGIT2_TAG ?= libgit2-1.3.0

# Allows for defining additional Docker buildx arguments,
# e.g. '--push'.
Expand All @@ -19,7 +19,7 @@ CRD_OPTIONS ?= crd:crdVersions=v1
REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel)

# Libgit2 version
LIBGIT2_VERSION ?= 1.1.1
LIBGIT2_VERSION ?= 1.3.0

# Other dependency versions
ENVTEST_BIN_VERSION ?= 1.19.2
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
github.com/go-git/go-billy/v5 v5.3.1
github.com/go-git/go-git/v5 v5.4.2
github.com/go-logr/logr v1.2.2
github.com/libgit2/git2go/v31 v31.7.6
github.com/libgit2/git2go/v33 v33.0.6
github.com/minio/minio-go/v7 v7.0.15
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.17.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -622,8 +622,8 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6Fm
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/libgit2/git2go/v31 v31.7.6 h1:jg/pNomrQULnafmfF6XTkozPX5ypyELoWErWkJuYPcI=
github.com/libgit2/git2go/v31 v31.7.6/go.mod h1:c/rkJcBcUFx6wHaT++UwNpKvIsmPNqCeQ/vzO4DrEec=
github.com/libgit2/git2go/v33 v33.0.6 h1:F//bA3/pgSTVq2hLNahhnof9NxyCzFF/c3MB6lb93Qo=
github.com/libgit2/git2go/v33 v33.0.6/go.mod h1:KdpqkU+6+++4oHna/MIOgx4GCQ92IPCdpVRMRI80J+4=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
Expand Down
10 changes: 5 additions & 5 deletions pkg/git/libgit2/checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (

"github.com/Masterminds/semver/v3"
"github.com/go-logr/logr"
git2go "github.com/libgit2/git2go/v31"
git2go "github.com/libgit2/git2go/v33"

"github.com/fluxcd/pkg/gitutil"
"github.com/fluxcd/pkg/version"
Expand Down Expand Up @@ -61,7 +61,7 @@ type CheckoutBranch struct {

func (c *CheckoutBranch) Checkout(ctx context.Context, path, url string, opts *git.AuthOptions) (*git.Commit, error) {
repo, err := git2go.Clone(url, path, &git2go.CloneOptions{
FetchOptions: &git2go.FetchOptions{
FetchOptions: git2go.FetchOptions{
DownloadTags: git2go.DownloadTagsNone,
RemoteCallbacks: RemoteCallbacks(ctx, opts),
ProxyOptions: git2go.ProxyOptions{Type: git2go.ProxyTypeAuto},
Expand Down Expand Up @@ -91,7 +91,7 @@ type CheckoutTag struct {

func (c *CheckoutTag) Checkout(ctx context.Context, path, url string, opts *git.AuthOptions) (*git.Commit, error) {
repo, err := git2go.Clone(url, path, &git2go.CloneOptions{
FetchOptions: &git2go.FetchOptions{
FetchOptions: git2go.FetchOptions{
DownloadTags: git2go.DownloadTagsAll,
RemoteCallbacks: RemoteCallbacks(ctx, opts),
ProxyOptions: git2go.ProxyOptions{Type: git2go.ProxyTypeAuto},
Expand All @@ -115,7 +115,7 @@ type CheckoutCommit struct {

func (c *CheckoutCommit) Checkout(ctx context.Context, path, url string, opts *git.AuthOptions) (*git.Commit, error) {
repo, err := git2go.Clone(url, path, &git2go.CloneOptions{
FetchOptions: &git2go.FetchOptions{
FetchOptions: git2go.FetchOptions{
DownloadTags: git2go.DownloadTagsNone,
RemoteCallbacks: RemoteCallbacks(ctx, opts),
ProxyOptions: git2go.ProxyOptions{Type: git2go.ProxyTypeAuto},
Expand Down Expand Up @@ -147,7 +147,7 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, opts *g
}

repo, err := git2go.Clone(url, path, &git2go.CloneOptions{
FetchOptions: &git2go.FetchOptions{
FetchOptions: git2go.FetchOptions{
DownloadTags: git2go.DownloadTagsAll,
RemoteCallbacks: RemoteCallbacks(ctx, opts),
ProxyOptions: git2go.ProxyOptions{Type: git2go.ProxyTypeAuto},
Expand Down
73 changes: 72 additions & 1 deletion pkg/git/libgit2/checkout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@ import (
"context"
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"testing"
"time"

git2go "github.com/libgit2/git2go/v31"
"github.com/fluxcd/pkg/gittestserver"
"github.com/fluxcd/pkg/ssh"
git2go "github.com/libgit2/git2go/v33"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"

"github.com/fluxcd/source-controller/pkg/git"
)

func TestCheckoutBranch_Checkout(t *testing.T) {
Expand Down Expand Up @@ -444,3 +450,68 @@ func mockSignature(time time.Time) *git2go.Signature {
When: time,
}
}

// This test is specifically to detect regression in libgit2's ED25519 key
// support for client authentication.
// Refer: https://github.com/fluxcd/source-controller/issues/399
func TestCheckout_ED25519(t *testing.T) {
g := NewWithT(t)
timeout := 5 * time.Second

// Create a git test server.
server, err := gittestserver.NewTempGitServer()
g.Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(server.Root())
server.Auth("test-user", "test-pswd")
server.AutoCreate()

server.KeyDir(filepath.Join(server.Root(), "keys"))
g.Expect(server.ListenSSH()).To(Succeed())

go func() {
server.StartSSH()
}()
defer server.StopSSH()

repoPath := "test.git"

err = server.InitRepo("testdata/git/repo", git.DefaultBranch, repoPath)
g.Expect(err).NotTo(HaveOccurred())

sshURL := server.SSHAddress()
repoURL := sshURL + "/" + repoPath

// Fetch host key.
u, err := url.Parse(sshURL)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(u.Host).ToNot(BeEmpty())
knownHosts, err := ssh.ScanHostKey(u.Host, timeout)
g.Expect(err).ToNot(HaveOccurred())

kp, err := ssh.NewEd25519Generator().Generate()
g.Expect(err).ToNot(HaveOccurred())

secret := corev1.Secret{
Data: map[string][]byte{
"identity": kp.PrivateKey,
"known_hosts": knownHosts,
},
}

authOpts, err := git.AuthOptionsFromSecret(repoURL, &secret)
g.Expect(err).ToNot(HaveOccurred())

// Prepare for checkout.
branchCheckoutStrat := &CheckoutBranch{Branch: git.DefaultBranch}
tmpDir, _ := os.MkdirTemp("", "test")
defer os.RemoveAll(tmpDir)

ctx, cancel := context.WithTimeout(context.TODO(), timeout)
defer cancel()

// Checkout the repo.
// This should always fail because the generated key above isn't present in
// the git server.
_, err = branchCheckoutStrat.Checkout(ctx, tmpDir, repoURL, authOpts)
g.Expect(err).To(BeNil())
}
1 change: 1 addition & 0 deletions pkg/git/libgit2/testdata/git/repo/foo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test file
Loading