Merge pull request #965 from pjbgf/fix-broken-fuzz
Migrate to Go Native fuzz and improve reliability
This commit is contained in:
commit
6dacad7f24
|
@ -1199,3 +1199,34 @@ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The built-in git_fs_path_basename_r() function is based on the
|
||||
Android implementation, BSD licensed:
|
||||
|
||||
Copyright (C) 2008 The Android Open Source Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
|
31
Makefile
31
Makefile
|
@ -33,7 +33,11 @@ REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel)
|
|||
BUILD_DIR := $(REPOSITORY_ROOT)/build
|
||||
|
||||
# Other dependency versions
|
||||
ENVTEST_BIN_VERSION ?= 1.19.2
|
||||
ENVTEST_BIN_VERSION ?= 1.24.0
|
||||
|
||||
# FUZZ_TIME defines the max amount of time, in Go Duration,
|
||||
# each fuzzer should run for.
|
||||
FUZZ_TIME ?= 1m
|
||||
|
||||
# Caches libgit2 versions per tag, "forcing" rebuild only when needed.
|
||||
LIBGIT2_PATH := $(BUILD_DIR)/libgit2/$(LIBGIT2_TAG)
|
||||
|
@ -134,7 +138,6 @@ tidy: ## Run go mod tidy
|
|||
fmt: ## Run go fmt against code
|
||||
go fmt ./...
|
||||
cd api; go fmt ./...
|
||||
cd tests/fuzz; go fmt .
|
||||
|
||||
vet: $(LIBGIT2) ## Run go vet against code
|
||||
go vet ./...
|
||||
|
@ -206,9 +209,9 @@ ifneq ($(shell grep -o 'LIBGIT2_IMG ?= \w.*' Makefile | cut -d ' ' -f 3):$(shell
|
|||
exit 1; \
|
||||
}
|
||||
endif
|
||||
ifneq ($(shell grep -o 'LIBGIT2_TAG ?= \w.*' Makefile | cut -d ' ' -f 3), $(shell grep -o "LIBGIT2_TAG=.*" tests/fuzz/oss_fuzz_build.sh | sed 's;LIBGIT2_TAG="$${LIBGIT2_TAG:-;;g' | sed 's;}";;g'))
|
||||
ifneq ($(shell grep -o 'LIBGIT2_TAG ?= \w.*' Makefile | cut -d ' ' -f 3), $(shell grep -o "LIBGIT2_TAG=.*" tests/fuzz/oss_fuzz_prebuild.sh | sed 's;LIBGIT2_TAG="$${LIBGIT2_TAG:-;;g' | sed 's;}";;g'))
|
||||
@{ \
|
||||
echo "LIBGIT2_TAG must match in both Makefile and tests/fuzz/oss_fuzz_build.sh"; \
|
||||
echo "LIBGIT2_TAG must match in both Makefile and tests/fuzz/oss_fuzz_prebuild.sh"; \
|
||||
exit 1; \
|
||||
}
|
||||
endif
|
||||
|
@ -232,26 +235,32 @@ rm -rf $$TMP_DIR ;\
|
|||
}
|
||||
endef
|
||||
|
||||
# Build fuzzers
|
||||
# Build fuzzers used by oss-fuzz.
|
||||
fuzz-build: $(LIBGIT2)
|
||||
rm -rf $(BUILD_DIR)/fuzz/
|
||||
mkdir -p $(BUILD_DIR)/fuzz/out/
|
||||
rm -rf $(shell pwd)/build/fuzz/
|
||||
mkdir -p $(shell pwd)/build/fuzz/out/
|
||||
|
||||
docker build . --pull --tag local-fuzzing:latest -f tests/fuzz/Dockerfile.builder
|
||||
docker build . --tag local-fuzzing:latest -f tests/fuzz/Dockerfile.builder
|
||||
docker run --rm \
|
||||
-e FUZZING_LANGUAGE=go -e SANITIZER=address \
|
||||
-e CIFUZZ_DEBUG='True' -e OSS_FUZZ_PROJECT_NAME=fluxcd \
|
||||
-v "$(BUILD_DIR)/fuzz/out":/out \
|
||||
-v "$(shell pwd)/build/fuzz/out":/out \
|
||||
local-fuzzing:latest
|
||||
|
||||
# Run each fuzzer once to ensure they will work when executed by oss-fuzz.
|
||||
fuzz-smoketest: fuzz-build
|
||||
docker run --rm \
|
||||
-v "$(BUILD_DIR)/fuzz/out":/out \
|
||||
-v "$(shell go env GOMODCACHE):/root/go/pkg/mod" \
|
||||
-v "$(shell pwd)/build/fuzz/out":/out \
|
||||
-v "$(shell pwd)/tests/fuzz/oss_fuzz_run.sh":/runner.sh \
|
||||
local-fuzzing:latest \
|
||||
bash -c "/runner.sh"
|
||||
|
||||
# Run fuzz tests for the duration set in FUZZ_TIME.
|
||||
fuzz-native:
|
||||
KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS) \
|
||||
FUZZ_TIME=$(FUZZ_TIME) \
|
||||
./tests/fuzz/native_go_run.sh
|
||||
|
||||
# Creates an env file that can be used to load all source-controller's dependencies
|
||||
# this is handy when you want to run adhoc debug sessions on tests or start the
|
||||
# controller in a new debug session.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
//go:build gofuzz_libfuzzer
|
||||
// +build gofuzz_libfuzzer
|
||||
|
||||
/*
|
||||
Copyright 2022 The Flux authors
|
||||
|
@ -61,7 +61,6 @@ import (
|
|||
"github.com/fluxcd/pkg/gittestserver"
|
||||
"github.com/fluxcd/pkg/runtime/testenv"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/fluxcd/source-controller/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -75,7 +74,7 @@ var (
|
|||
cfg *rest.Config
|
||||
testEnv *testenv.Environment
|
||||
|
||||
storage *controllers.Storage
|
||||
storage *Storage
|
||||
|
||||
examplePublicKey []byte
|
||||
examplePrivateKey []byte
|
||||
|
@ -87,277 +86,140 @@ var (
|
|||
var testFiles embed.FS
|
||||
|
||||
const (
|
||||
defaultBinVersion = "1.23"
|
||||
defaultBinVersion = "1.24"
|
||||
lettersAndNumbers = "abcdefghijklmnopqrstuvwxyz123456789"
|
||||
lettersNumbersAndDash = "abcdefghijklmnopqrstuvwxyz123456789-"
|
||||
)
|
||||
|
||||
func envtestBinVersion() string {
|
||||
if binVersion := os.Getenv("ENVTEST_BIN_VERSION"); binVersion != "" {
|
||||
return binVersion
|
||||
}
|
||||
return defaultBinVersion
|
||||
}
|
||||
|
||||
func ensureDependencies() error {
|
||||
if _, err := os.Stat("/.dockerenv"); os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if os.Getenv("KUBEBUILDER_ASSETS") == "" {
|
||||
binVersion := envtestBinVersion()
|
||||
cmd := exec.Command("/usr/bin/bash", "-c", fmt.Sprintf(`go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest && \
|
||||
/root/go/bin/setup-envtest use -p path %s`, binVersion))
|
||||
|
||||
cmd.Env = append(os.Environ(), "GOPATH=/root/go")
|
||||
assetsPath, err := cmd.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Setenv("KUBEBUILDER_ASSETS", string(assetsPath))
|
||||
}
|
||||
|
||||
// Output all embedded testdata files
|
||||
embedDirs := []string{"testdata/crd", "testdata/certs"}
|
||||
for _, dir := range embedDirs {
|
||||
err := os.MkdirAll(dir, 0o700)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mkdir %s: %v", dir, err)
|
||||
}
|
||||
|
||||
templates, err := fs.ReadDir(testFiles, dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading embedded dir: %v", err)
|
||||
}
|
||||
|
||||
for _, template := range templates {
|
||||
fileName := fmt.Sprintf("%s/%s", dir, template.Name())
|
||||
fmt.Println(fileName)
|
||||
|
||||
data, err := testFiles.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading embedded file %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
os.WriteFile(fileName, data, 0o600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("writing %s: %v", fileName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startEnvServer(func(m manager.Manager) {
|
||||
utilruntime.Must((&controllers.GitRepositoryReconciler{
|
||||
Client: m.GetClient(),
|
||||
Storage: storage,
|
||||
}).SetupWithManager(m))
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func startEnvServer(setupReconcilers func(manager.Manager)) *envtest.Environment {
|
||||
testEnv := &envtest.Environment{
|
||||
CRDDirectoryPaths: []string{filepath.Join("testdata", "crd")},
|
||||
}
|
||||
fmt.Println("Starting the test environment")
|
||||
cfg, err := testEnv.Start()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to start the test environment manager: %v", err))
|
||||
}
|
||||
|
||||
utilruntime.Must(loadExampleKeys())
|
||||
utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme))
|
||||
|
||||
tmpStoragePath, err := os.MkdirTemp("", "source-controller-storage-")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpStoragePath)
|
||||
storage, err = controllers.NewStorage(tmpStoragePath, "localhost:5050", time.Minute*1, 2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// serve artifacts from the filesystem, as done in main.go
|
||||
fs := http.FileServer(http.Dir(tmpStoragePath))
|
||||
http.Handle("/", fs)
|
||||
go http.ListenAndServe(":5050", nil)
|
||||
|
||||
cert, err := tls.X509KeyPair(examplePublicKey, examplePrivateKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(exampleCA)
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caCertPool,
|
||||
}
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
|
||||
var transport = httptransport.NewClient(&http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
},
|
||||
})
|
||||
gitclient.InstallProtocol("https", transport)
|
||||
|
||||
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if k8sClient == nil {
|
||||
panic("cfg is nil but should not be")
|
||||
}
|
||||
|
||||
k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
|
||||
Scheme: scheme.Scheme,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
setupReconcilers(k8sManager)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
go func() {
|
||||
fmt.Println("Starting k8sManager...")
|
||||
utilruntime.Must(k8sManager.Start(context.TODO()))
|
||||
}()
|
||||
|
||||
return testEnv
|
||||
}
|
||||
|
||||
// FuzzRandomGitFiles implements a fuzzer that
|
||||
// targets the GitRepository reconciler.
|
||||
func FuzzRandomGitFiles(data []byte) int {
|
||||
initter.Do(func() {
|
||||
utilruntime.Must(ensureDependencies())
|
||||
func FuzzRandomGitFiles(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
initter.Do(func() {
|
||||
utilruntime.Must(ensureDependencies())
|
||||
})
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
namespace, deleteNamespace, err := createNamespace(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer deleteNamespace()
|
||||
|
||||
gitServerURL, stopGitServer := createGitServer(f)
|
||||
defer stopGitServer()
|
||||
|
||||
fs := memfs.New()
|
||||
gitrepo, err := git.Init(memory.NewStorage(), fs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
wt, err := gitrepo.Worktree()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create random files for the git source
|
||||
err = createRandomFiles(f, fs, wt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
commit, err := pushFilesToGit(gitrepo, wt, gitServerURL.String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
created, err := createGitRepository(f, gitServerURL.String(), commit.String(), namespace.Name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = k8sClient.Create(context.Background(), created)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer k8sClient.Delete(context.Background(), created)
|
||||
|
||||
// Let the reconciler do its thing:
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
})
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
namespace, deleteNamespace, err := createNamespace(f)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
defer deleteNamespace()
|
||||
|
||||
gitServerURL, stopGitServer := createGitServer(f)
|
||||
defer stopGitServer()
|
||||
|
||||
fs := memfs.New()
|
||||
gitrepo, err := git.Init(memory.NewStorage(), fs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
wt, err := gitrepo.Worktree()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create random files for the git source
|
||||
err = createRandomFiles(f, fs, wt)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
commit, err := pushFilesToGit(gitrepo, wt, gitServerURL.String())
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
created, err := createGitRepository(f, gitServerURL.String(), commit.String(), namespace.Name)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
err = k8sClient.Create(context.Background(), created)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
defer k8sClient.Delete(context.Background(), created)
|
||||
|
||||
// Let the reconciler do its thing:
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// FuzzGitResourceObject implements a fuzzer that targets
|
||||
// the GitRepository reconciler.
|
||||
func FuzzGitResourceObject(data []byte) int {
|
||||
initter.Do(func() {
|
||||
utilruntime.Must(ensureDependencies())
|
||||
func FuzzGitResourceObject(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
initter.Do(func() {
|
||||
utilruntime.Must(ensureDependencies())
|
||||
})
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
|
||||
// Create this early because if it fails, then the fuzzer
|
||||
// does not need to proceed.
|
||||
repository := &sourcev1.GitRepository{}
|
||||
err := f.GenerateStruct(repository)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
metaName, err := f.GetStringFrom(lettersNumbersAndDash, 59)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
gitServerURL, stopGitServer := createGitServer(f)
|
||||
defer stopGitServer()
|
||||
|
||||
fs := memfs.New()
|
||||
gitrepo, err := git.Init(memory.NewStorage(), fs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
wt, err := gitrepo.Worktree()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Add a file
|
||||
ff, _ := fs.Create("fixture")
|
||||
_ = ff.Close()
|
||||
_, err = wt.Add(fs.Join("fixture"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
commit, err := pushFilesToGit(gitrepo, wt, gitServerURL.String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
namespace, deleteNamespace, err := createNamespace(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer deleteNamespace()
|
||||
|
||||
repository.Spec.URL = gitServerURL.String()
|
||||
repository.Spec.Verification.Mode = "head"
|
||||
repository.Spec.SecretRef = nil
|
||||
|
||||
reference := &sourcev1.GitRepositoryRef{Branch: "some-branch"}
|
||||
reference.Commit = strings.Replace(reference.Commit, "<commit>", commit.String(), 1)
|
||||
repository.Spec.Reference = reference
|
||||
|
||||
repository.ObjectMeta = metav1.ObjectMeta{
|
||||
Name: metaName,
|
||||
Namespace: namespace.Name,
|
||||
}
|
||||
err = k8sClient.Create(context.Background(), repository)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer k8sClient.Delete(context.Background(), repository)
|
||||
|
||||
// Let the reconciler do its thing.
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
})
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
|
||||
// Create this early because if it fails, then the fuzzer
|
||||
// does not need to proceed.
|
||||
repository := &sourcev1.GitRepository{}
|
||||
err := f.GenerateStruct(repository)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
metaName, err := f.GetStringFrom(lettersNumbersAndDash, 59)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
gitServerURL, stopGitServer := createGitServer(f)
|
||||
defer stopGitServer()
|
||||
|
||||
fs := memfs.New()
|
||||
gitrepo, err := git.Init(memory.NewStorage(), fs)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
wt, err := gitrepo.Worktree()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Add a file
|
||||
ff, _ := fs.Create("fixture")
|
||||
_ = ff.Close()
|
||||
_, err = wt.Add(fs.Join("fixture"))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
commit, err := pushFilesToGit(gitrepo, wt, gitServerURL.String())
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
namespace, deleteNamespace, err := createNamespace(f)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
defer deleteNamespace()
|
||||
|
||||
repository.Spec.URL = gitServerURL.String()
|
||||
repository.Spec.Verification.Mode = "head"
|
||||
repository.Spec.SecretRef = nil
|
||||
|
||||
reference := &sourcev1.GitRepositoryRef{Branch: "some-branch"}
|
||||
reference.Commit = strings.Replace(reference.Commit, "<commit>", commit.String(), 1)
|
||||
repository.Spec.Reference = reference
|
||||
|
||||
repository.ObjectMeta = metav1.ObjectMeta{
|
||||
Name: metaName,
|
||||
Namespace: namespace.Name,
|
||||
}
|
||||
err = k8sClient.Create(context.Background(), repository)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
defer k8sClient.Delete(context.Background(), repository)
|
||||
|
||||
// Let the reconciler do its thing.
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
return 1
|
||||
}
|
||||
|
||||
func loadExampleKeys() (err error) {
|
||||
|
@ -527,3 +389,141 @@ func createRandomFiles(f *fuzz.ConsumeFuzzer, fs billy.Filesystem, wt *git.Workt
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func envtestBinVersion() string {
|
||||
if binVersion := os.Getenv("ENVTEST_BIN_VERSION"); binVersion != "" {
|
||||
return binVersion
|
||||
}
|
||||
return defaultBinVersion
|
||||
}
|
||||
|
||||
func ensureDependencies() error {
|
||||
if _, err := os.Stat("/.dockerenv"); os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if os.Getenv("KUBEBUILDER_ASSETS") == "" {
|
||||
binVersion := envtestBinVersion()
|
||||
cmd := exec.Command("/usr/bin/bash", "-c", fmt.Sprintf(`go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest && \
|
||||
/root/go/bin/setup-envtest use -p path %s`, binVersion))
|
||||
|
||||
cmd.Env = append(os.Environ(), "GOPATH=/root/go")
|
||||
assetsPath, err := cmd.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Setenv("KUBEBUILDER_ASSETS", string(assetsPath))
|
||||
}
|
||||
|
||||
// Output all embedded testdata files
|
||||
embedDirs := []string{"testdata/crd", "testdata/certs"}
|
||||
for _, dir := range embedDirs {
|
||||
err := os.MkdirAll(dir, 0o700)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mkdir %s: %v", dir, err)
|
||||
}
|
||||
|
||||
templates, err := fs.ReadDir(testFiles, dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading embedded dir: %v", err)
|
||||
}
|
||||
|
||||
for _, template := range templates {
|
||||
fileName := fmt.Sprintf("%s/%s", dir, template.Name())
|
||||
fmt.Println(fileName)
|
||||
|
||||
data, err := testFiles.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading embedded file %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
os.WriteFile(fileName, data, 0o600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("writing %s: %v", fileName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startEnvServer(func(m manager.Manager) {
|
||||
utilruntime.Must((&GitRepositoryReconciler{
|
||||
Client: m.GetClient(),
|
||||
Storage: storage,
|
||||
}).SetupWithManager(m))
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func startEnvServer(setupReconcilers func(manager.Manager)) *envtest.Environment {
|
||||
testEnv := &envtest.Environment{
|
||||
CRDDirectoryPaths: []string{filepath.Join("testdata", "crd")},
|
||||
}
|
||||
fmt.Println("Starting the test environment")
|
||||
cfg, err := testEnv.Start()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to start the test environment manager: %v", err))
|
||||
}
|
||||
|
||||
utilruntime.Must(loadExampleKeys())
|
||||
utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme))
|
||||
|
||||
tmpStoragePath, err := os.MkdirTemp("", "source-controller-storage-")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpStoragePath)
|
||||
storage, err = NewStorage(tmpStoragePath, "localhost:5050", time.Minute*1, 2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// serve artifacts from the filesystem, as done in main.go
|
||||
fs := http.FileServer(http.Dir(tmpStoragePath))
|
||||
http.Handle("/", fs)
|
||||
go http.ListenAndServe(":5050", nil)
|
||||
|
||||
cert, err := tls.X509KeyPair(examplePublicKey, examplePrivateKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(exampleCA)
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caCertPool,
|
||||
}
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
|
||||
var transport = httptransport.NewClient(&http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
},
|
||||
})
|
||||
gitclient.InstallProtocol("https", transport)
|
||||
|
||||
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if k8sClient == nil {
|
||||
panic("cfg is nil but should not be")
|
||||
}
|
||||
|
||||
k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
|
||||
Scheme: scheme.Scheme,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
setupReconcilers(k8sManager)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
go func() {
|
||||
fmt.Println("Starting k8sManager...")
|
||||
utilruntime.Must(k8sManager.Start(context.TODO()))
|
||||
}()
|
||||
|
||||
return testEnv
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
FROM gcr.io/oss-fuzz-base/base-builder-go-codeintelligencetesting
|
||||
FROM gcr.io/oss-fuzz-base/base-builder-go
|
||||
|
||||
RUN apt-get update && apt-get install -y cmake pkg-config
|
||||
|
||||
COPY ./ $GOPATH/src/github.com/fluxcd/source-controller/
|
||||
COPY ./tests/fuzz/oss_fuzz_build.sh $SRC/build.sh
|
||||
COPY tests/fuzz/compile_native_go_fuzzer /usr/local/bin/
|
||||
|
||||
WORKDIR $SRC
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
# fuzz testing
|
||||
|
||||
Flux is part of Google's [oss fuzz] program which provides continuous fuzzing for
|
||||
open source projects.
|
||||
|
||||
The long running fuzzing execution is configured in the [oss-fuzz repository].
|
||||
Shorter executions are done on a per-PR basis, configured as a [github workflow].
|
||||
|
||||
### Testing locally
|
||||
|
||||
Build fuzzers:
|
||||
|
||||
```bash
|
||||
make fuzz-build
|
||||
```
|
||||
All fuzzers will be built into `./build/fuzz/out`.
|
||||
|
||||
Smoke test fuzzers:
|
||||
|
||||
All the fuzzers will be built and executed once, to ensure they are fully functional.
|
||||
|
||||
```bash
|
||||
make fuzz-smoketest
|
||||
```
|
||||
|
||||
Run fuzzer locally:
|
||||
```bash
|
||||
./build/fuzz/out/fuzz_conditions_match
|
||||
```
|
||||
|
||||
Run fuzzer inside a container:
|
||||
|
||||
```bash
|
||||
docker run --rm -ti \
|
||||
-v "$(pwd)/build/fuzz/out":/out \
|
||||
gcr.io/oss-fuzz/fluxcd \
|
||||
/out/fuzz_conditions_match
|
||||
```
|
||||
|
||||
### Caveats of creating oss-fuzz compatible tests
|
||||
|
||||
#### Segregate fuzz tests
|
||||
|
||||
OSS-Fuzz does not properly support mixed `*_test.go` files, in which there is a combination
|
||||
of fuzz and non-fuzz tests. To mitigate this problem, ensure your fuzz tests are not in the
|
||||
same file as other Go tests. As a pattern, call your fuzz test files `*_fuzz_test.go`.
|
||||
|
||||
#### Build tags to avoid conflicts when running Go tests
|
||||
|
||||
Due to the issue above, code duplication will occur when creating fuzz tests that rely on
|
||||
helper functions that are shared with other tests. To avoid build issues, add a conditional
|
||||
build tag at the top of the `*_fuzz_test.go` file:
|
||||
```go
|
||||
//go:build gofuzz_libfuzzer
|
||||
// +build gofuzz_libfuzzer
|
||||
```
|
||||
|
||||
The build tag above is set at [go-118-fuzz-build].
|
||||
At this point in time we can't pass on specific tags from [compile_native_go_fuzzer].
|
||||
|
||||
### Running oss-fuzz locally
|
||||
|
||||
The `make fuzz-smoketest` is meant to be an easy way to reproduce errors that may occur
|
||||
upstream. If our checks ever run out of sync with upstream, the upstream tests can be
|
||||
executed locally with:
|
||||
|
||||
```
|
||||
git clone --depth 1 https://github.com/google/oss-fuzz
|
||||
cd oss-fuzz
|
||||
python infra/helper.py build_image fluxcd
|
||||
python infra/helper.py build_fuzzers --sanitizer address --architecture x86_64 fluxcd
|
||||
python infra/helper.py check_build --sanitizer address --architecture x86_64 fluxcd
|
||||
```
|
||||
|
||||
For latest info on testing oss-fuzz locally, refer to the [upstream guide].
|
||||
|
||||
[oss fuzz]: https://github.com/google/oss-fuzz
|
||||
[oss-fuzz repository]: https://github.com/google/oss-fuzz/tree/master/projects/fluxcd
|
||||
[github workflow]: .github/workflows/cifuzz.yaml
|
||||
[upstream guide]: https://google.github.io/oss-fuzz/getting-started/new-project-guide/#testing-locally
|
||||
[go-118-fuzz-build]: https://github.com/AdamKorcz/go-118-fuzz-build/blob/b2031950a318d4f2dcf3ec3e128f904d5cf84623/main.go#L40
|
||||
[compile_native_go_fuzzer]: https://github.com/google/oss-fuzz/blob/c2d827cb78529fdc757c9b0b4fea0f1238a54814/infra/base-images/base-builder/compile_native_go_fuzzer#L32
|
|
@ -0,0 +1,62 @@
|
|||
#!/bin/bash -eux
|
||||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# This is a copy of the upstream script which is only needed to link
|
||||
# additional static libraries. Orignal source:
|
||||
#
|
||||
# https://github.com/google/oss-fuzz/blob/9e8dd47cb902545efc60a5580126adc36d70bae3/infra/base-images/base-builder/compile_native_go_fuzzer
|
||||
|
||||
function build_native_go_fuzzer() {
|
||||
fuzzer=$1
|
||||
function=$2
|
||||
path=$3
|
||||
tags="-tags gofuzz"
|
||||
|
||||
if [[ $SANITIZER == *coverage* ]]; then
|
||||
current_dir=$(pwd)
|
||||
mkdir $OUT/rawfuzzers || true
|
||||
cd $abs_file_dir
|
||||
go test -c -run $fuzzer -o $OUT/$fuzzer -cover
|
||||
cp "${fuzzer_filename}" "${OUT}/rawfuzzers/${fuzzer}"
|
||||
cd $current_dir
|
||||
else
|
||||
go-118-fuzz-build -o $fuzzer.a -func $function $abs_file_dir
|
||||
# TODO: upstream support for linking $ADDITIONAL_LIBS
|
||||
$CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer \
|
||||
$ADDITIONAL_LIBS
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
path=$1
|
||||
function=$2
|
||||
fuzzer=$3
|
||||
tags="-tags gofuzz"
|
||||
|
||||
# Get absolute path.
|
||||
abs_file_dir=$(go list $tags -f {{.Dir}} $path)
|
||||
|
||||
# TODO(adamkorcz): Get rid of "-r" flag here.
|
||||
fuzzer_filename=$(grep -r -l --include='*.go' -s "$function" "${abs_file_dir}")
|
||||
|
||||
# Test if file contains a line with "func $function" and "testing.F".
|
||||
if [ $(grep -r "func $function" $fuzzer_filename | grep "testing.F" | wc -l) -eq 1 ]
|
||||
then
|
||||
build_native_go_fuzzer $fuzzer $function $abs_file_dir
|
||||
else
|
||||
echo "Could not find the function: func ${function}(f *testing.F)"
|
||||
fi
|
|
@ -1,7 +0,0 @@
|
|||
module github.com/fluxcd/source-controller/tests/fuzz
|
||||
|
||||
go 1.18
|
||||
|
||||
replace github.com/fluxcd/source-controller/api => ../../api
|
||||
|
||||
replace github.com/fluxcd/source-controller => ../../
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2022 The Flux authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
# This script iterates through all go fuzzing targets, running each one
|
||||
# through the period of time established by FUZZ_TIME.
|
||||
|
||||
FUZZ_TIME=${FUZZ_TIME:-"5s"}
|
||||
|
||||
# kustomization_fuzzer_test is not fully compatible with Go native fuzz,
|
||||
# so it is ignored here.
|
||||
test_files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' . | \
|
||||
grep -v "controllers_fuzzer_test.go")
|
||||
|
||||
for file in ${test_files}
|
||||
do
|
||||
targets=$(grep -oP 'func \K(Fuzz\w*)' "${file}")
|
||||
for target_name in ${targets}
|
||||
do
|
||||
echo "Running ${file}.${target_name} for ${FUZZ_TIME}."
|
||||
file_dir=$(dirname "${file}")
|
||||
|
||||
go test -fuzz="^${target_name}\$" -fuzztime "${FUZZ_TIME}" "${file_dir}"
|
||||
done
|
||||
done
|
|
@ -16,93 +16,65 @@
|
|||
|
||||
set -euxo pipefail
|
||||
|
||||
LIBGIT2_TAG="${LIBGIT2_TAG:-v0.4.0}"
|
||||
# This file aims for:
|
||||
# - Dynamically discover and build all fuzz tests within the repository.
|
||||
# - Work for both local make fuzz-smoketest and the upstream oss-fuzz.
|
||||
|
||||
GOPATH="${GOPATH:-/root/go}"
|
||||
GO_SRC="${GOPATH}/src"
|
||||
PROJECT_PATH="github.com/fluxcd/source-controller"
|
||||
|
||||
pushd "${GO_SRC}/${PROJECT_PATH}"
|
||||
|
||||
export TARGET_DIR="$(/bin/pwd)/build/libgit2/${LIBGIT2_TAG}"
|
||||
|
||||
# For most cases, libgit2 will already be present.
|
||||
# The exception being at the oss-fuzz integration.
|
||||
if [ ! -d "${TARGET_DIR}" ]; then
|
||||
curl -o output.tar.gz -LO "https://github.com/fluxcd/golang-with-libgit2/releases/download/${LIBGIT2_TAG}/linux-x86_64-libgit2-only.tar.gz"
|
||||
|
||||
DIR=linux-libgit2-only
|
||||
NEW_DIR="$(/bin/pwd)/build/libgit2/${LIBGIT2_TAG}"
|
||||
INSTALLED_DIR="/home/runner/work/golang-with-libgit2/golang-with-libgit2/build/${DIR}"
|
||||
|
||||
mkdir -p ./build/libgit2
|
||||
|
||||
tar -xf output.tar.gz
|
||||
rm output.tar.gz
|
||||
mv "${DIR}" "${LIBGIT2_TAG}"
|
||||
mv "${LIBGIT2_TAG}/" "./build/libgit2"
|
||||
|
||||
# Update the prefix paths included in the .pc files.
|
||||
# This will make it easier to update to the location in which they will be used.
|
||||
find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} sed -i "s;${INSTALLED_DIR};${NEW_DIR};g" {}
|
||||
fi
|
||||
|
||||
apt-get update && apt-get install -y pkg-config
|
||||
|
||||
export CGO_ENABLED=1
|
||||
export PKG_CONFIG_PATH="${TARGET_DIR}/lib/pkgconfig"
|
||||
export CGO_LDFLAGS="$(pkg-config --libs --static --cflags libgit2)"
|
||||
export LIBRARY_PATH="${TARGET_DIR}/lib"
|
||||
export CGO_CFLAGS="-I${TARGET_DIR}/include"
|
||||
|
||||
go get -d github.com/AdaLogics/go-fuzz-headers
|
||||
|
||||
# The implementation of libgit2 is sensitive to the versions of git2go.
|
||||
# Leaving it to its own devices, the minimum version of git2go used may not
|
||||
# be compatible with the currently implemented version. Hence the modifications
|
||||
# of the existing go.mod.
|
||||
sed "s;\./api;$(/bin/pwd)/api;g" go.mod > tests/fuzz/go.mod
|
||||
sed -i 's;module github.com/fluxcd/source-controller;module github.com/fluxcd/source-controller/tests/fuzz;g' tests/fuzz/go.mod
|
||||
echo "replace github.com/fluxcd/source-controller => $(/bin/pwd)/" >> tests/fuzz/go.mod
|
||||
|
||||
cp go.sum tests/fuzz/go.sum
|
||||
|
||||
pushd "tests/fuzz"
|
||||
|
||||
go mod download
|
||||
|
||||
go get -d github.com/AdaLogics/go-fuzz-headers
|
||||
go get -d github.com/fluxcd/source-controller
|
||||
|
||||
# Setup files to be embedded into controllers_fuzzer.go's testFiles variable.
|
||||
mkdir -p testdata/crd
|
||||
cp ../../config/crd/bases/*.yaml testdata/crd/
|
||||
cp -r ../../controllers/testdata/certs testdata/
|
||||
|
||||
go get -d github.com/AdaLogics/go-fuzz-headers
|
||||
|
||||
# Using compile_go_fuzzer to compile fails when statically linking libgit2 dependencies
|
||||
# via CFLAGS/CXXFLAGS.
|
||||
function go_compile(){
|
||||
function=$1
|
||||
fuzzer=$2
|
||||
|
||||
if [[ $SANITIZER = *coverage* ]]; then
|
||||
# ref: https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_go_fuzzer
|
||||
compile_go_fuzzer "${PROJECT_PATH}/tests/fuzz" "${function}" "${fuzzer}"
|
||||
else
|
||||
go-fuzz -tags gofuzz -func="${function}" -o "${fuzzer}.a" .
|
||||
${CXX} ${CXXFLAGS} ${LIB_FUZZING_ENGINE} -o "${OUT}/${fuzzer}" \
|
||||
"${fuzzer}.a" "${TARGET_DIR}/lib/libgit2.a" \
|
||||
-fsanitize="${SANITIZER}"
|
||||
fi
|
||||
# install_deps installs all dependencies needed for upstream oss-fuzz.
|
||||
# Unfortunately we can't pin versions here, as we want to always
|
||||
# have the latest, so that we can reproduce errors occuring upstream.
|
||||
install_deps(){
|
||||
if ! command -v go-118-fuzz-build &> /dev/null; then
|
||||
go install github.com/AdamKorcz/go-118-fuzz-build@latest
|
||||
fi
|
||||
}
|
||||
|
||||
go_compile FuzzRandomGitFiles fuzz_gitrepository_fuzzer
|
||||
go_compile FuzzGitResourceObject fuzz_git_resource_object
|
||||
install_deps
|
||||
|
||||
# By now testdata is embedded in the binaries and no longer needed.
|
||||
# Remove the dir given that it will be owned by root otherwise.
|
||||
rm -rf testdata/
|
||||
cd "${GO_SRC}/${PROJECT_PATH}"
|
||||
|
||||
popd
|
||||
popd
|
||||
# Ensure any project-specific requirements are catered for ahead of
|
||||
# the generic build process.
|
||||
if [ -f "tests/fuzz/oss_fuzz_prebuild.sh" ]; then
|
||||
. tests/fuzz/oss_fuzz_prebuild.sh
|
||||
fi
|
||||
|
||||
modules=$(find . -mindepth 1 -maxdepth 4 -type f -name 'go.mod' | cut -c 3- | sed 's|/[^/]*$$||' | sort -u | sed 's;/go.mod;;g' | sed 's;go.mod;.;g')
|
||||
|
||||
for module in ${modules}; do
|
||||
|
||||
cd "${GO_SRC}/${PROJECT_PATH}/${module}"
|
||||
|
||||
test_files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' . || echo "")
|
||||
if [ -z "${test_files}" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
go get github.com/AdamKorcz/go-118-fuzz-build/testing
|
||||
|
||||
# Iterate through all Go Fuzz targets, compiling each into a fuzzer.
|
||||
for file in ${test_files}; do
|
||||
# If the subdir is a module, skip this file, as it will be handled
|
||||
# at the next iteration of the outer loop.
|
||||
if [ -f "$(dirname "${file}")/go.mod" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
targets=$(grep -oP 'func \K(Fuzz\w*)' "${file}")
|
||||
for target_name in ${targets}; do
|
||||
# Transform module path into module name (e.g. git/libgit2 to git_libgit2).
|
||||
module_name="$(echo ${module} | tr / _)_"
|
||||
# Compose fuzzer name based on the lowercase version of the func names.
|
||||
# The module name is added after the fuzz prefix, for better discoverability.
|
||||
fuzzer_name=$(echo "${target_name}" | tr '[:upper:]' '[:lower:]' | sed "s;fuzz_;fuzz_${module_name//._/};g")
|
||||
target_dir=$(dirname "${file}")
|
||||
|
||||
echo "Building ${file}.${target_name} into ${fuzzer_name}"
|
||||
compile_native_go_fuzzer "${target_dir}" "${target_name}" "${fuzzer_name}"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2022 The Flux authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
# This file is executed by upstream oss-fuzz for any requirements that
|
||||
# are specific for building this project.
|
||||
|
||||
# Some tests requires embedded resources. Embedding does not allow
|
||||
# for traversing into ascending dirs, therefore we copy those contents here:
|
||||
mkdir -p controllers/testdata/crd
|
||||
cp config/crd/bases/*.yaml controllers/testdata/crd/
|
||||
|
||||
# libgit2, cmake and pkg-config are requirements to support libgit2.
|
||||
LIBGIT2_TAG="${LIBGIT2_TAG:-v0.4.0}"
|
||||
|
||||
# Avoid updating apt get and installing dependencies, if they are already in place.
|
||||
if (! command -v cmake &> /dev/null) || (! command -v pkg-config &> /dev/null) then
|
||||
apt-get update && apt-get install -y cmake pkg-config
|
||||
fi
|
||||
|
||||
export TARGET_DIR="$(/bin/pwd)/build/libgit2/${LIBGIT2_TAG}"
|
||||
|
||||
# For most cases, libgit2 will already be present.
|
||||
# The exception being at the oss-fuzz integration.
|
||||
if [ ! -d "${TARGET_DIR}" ]; then
|
||||
curl --connect-timeout 2 --retry 3 --retry-delay 1 --retry-max-time 30 \
|
||||
-o output.tar.gz -LO "https://github.com/fluxcd/golang-with-libgit2/releases/download/${LIBGIT2_TAG}/linux-$(uname -m)-libgit2-only.tar.gz"
|
||||
|
||||
DIR=linux-libgit2-only
|
||||
NEW_DIR="$(/bin/pwd)/build/libgit2/${LIBGIT2_TAG}"
|
||||
INSTALLED_DIR="/home/runner/work/golang-with-libgit2/golang-with-libgit2/build/${DIR}"
|
||||
|
||||
mkdir -p ./build/libgit2
|
||||
|
||||
tar -xf output.tar.gz
|
||||
rm output.tar.gz
|
||||
mv "${DIR}" "${LIBGIT2_TAG}"
|
||||
mv "${LIBGIT2_TAG}/" "./build/libgit2"
|
||||
|
||||
# Update the prefix paths included in the .pc files.
|
||||
# This will make it easier to update to the location in which they will be used.
|
||||
find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} sed -i "s;${INSTALLED_DIR};${NEW_DIR};g" {}
|
||||
fi
|
||||
|
||||
export CGO_ENABLED=1
|
||||
export LIBRARY_PATH="${TARGET_DIR}/lib"
|
||||
export PKG_CONFIG_PATH="${TARGET_DIR}/lib/pkgconfig"
|
||||
export CGO_CFLAGS="-I${TARGET_DIR}/include"
|
||||
export CGO_LDFLAGS="$(pkg-config --libs --static --cflags libgit2)"
|
||||
|
||||
export ADDITIONAL_LIBS="${TARGET_DIR}/lib/libgit2.a"
|
Loading…
Reference in New Issue