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

ZEP-0010: Vendoring external dependencies #11

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
189 changes: 189 additions & 0 deletions 10-vendor-dependencies/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# ZEP-10: Vendoring external dependencies

<!-- toc -->
- [Summary](#summary)
- [Motivation](#motivation)
- [Goals](#goals)
- [Non-Goals](#non-goals)
- [Proposal](#proposal)
- [User Stories (Optional)](#user-stories-optional)
- [Story 1](#story-1)
- [Story 2](#story-2)
- [Risks and Mitigations](#risks-and-mitigations)
- [Design Details](#design-details)
- [Test Plan](#test-plan)
- [Prerequisite testing updates](#prerequisite-testing-updates)
- [Unit tests](#unit-tests)
- [e2e tests](#e2e-tests)
- [Graduation Criteria](#graduation-criteria)
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
- [Version Skew Strategy](#version-skew-strategy)
- [Implementation History](#implementation-history)
- [Drawbacks](#drawbacks)
- [Alternatives](#alternatives)
- [Infrastructure Needed (Optional)](#infrastructure-needed-optional)
<!-- /toc -->

## Summary

Vendoring external dependencies involves copying third-party libraries code
directly into the project under a `vendor/` directory. This document outlines
the advantages and disadvantages of this approach, aiming to support the adoption
of vendoring for the Zarf project.

## Motivation

Zarf is [advertised](https://docs.zarf.dev/) as:

> a free and open-source tool that enables declarative creation & distribution
> of software into air-gapped/constrained/standalone environments.

Its primary objective is to facilitate software delivery to disconnected environments.
Consequently, it is logical for Zarf itself to support building in such environments.

### Goals

- Enable hermetic (reproducible and consistent) builds.
- Support builds in disconnected environments.
- Provide tighter control over dependencies.

### Non-Goals

- Modify existing dependency management tool.

## Proposal

The Go community has long debated the merits of vendoring dependencies. Research
reveals compelling arguments on both sides. This section explores these arguments
and explains why vendoring was chosen for the Zarf project.

#### Pros

1. **Reproducible and Consistent Builds.**

Vendoring supports [hermetic builds](https://sre.google/sre-book/release-engineering/#hermetic-builds-nqslhnid),
ensuring consistent and predictable outcomes.

2. **Self-contained Builds.**

Vendoring allows disconnected, self-contained builds immediately after cloning
the repository, with only the Go compiler required.

3. **Faster CI/CD Builds Times.**

Local dependencies eliminate the need to fetch external dependencies, speeding
up builds.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is especially nice for Windows builds, where github actions caching doesn't work, so pulling all the Zarf dependencies for unit tests takes about 10 minutes



4. **Resilience to External Change.**

A local copy of dependencies mitigates risks from upstream issues, such as projects
being deleted or altered unexpectedly.

5. **Auditability and Control.**

Vendored dependencies make it easier to audit code and monitor license changes,
preventing unwanted changes like license incompatibility, excessive dependencies
growth.

### Cons

1. **Increased repository size.**

Vendoring adds to repository's size. However, disk space is inexpensive, and many
large projects (eg. [Kubernetes](https://github.com/kubernetes/kubernetes/), with
a `vendor/` directory ~70MB) have benefited from improving their dependency management.
For Zarf, vendoring would increase the repository size by approximately 410MB.
Copy link
Contributor

Choose a reason for hiding this comment

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

I would be interested to see the cost of a vendor folder storage on the .git folder. I'm not sure if there is an easy way to calculate that. The Kubernetes .git folder is ~1.2 GBs. There have surely been a lot of changes in Kubernetes itself, but I wonder how much of .git folder is from vendor diffs.


2. **Maintenance Overhead.**

Developers must run `go mod tidy` and `go mod vendor` when modifying dependencies.
However, existing checks ensure consistency in `go.mod` and `go.sum`, and these
can be extended to validate the `vendor/` directory.

3. **Cluttered Repository History.**

Vendored updates may add noise to the commit history. However, Zarf's history
already includes [multiple entries from dependabot](https://github.com/zarf-dev/zarf/commits?author=dependabot%5Bbot%5D),
so the additional entires should not pose significant issues.


### User Stories (Optional)

#### Story 1

As a developer, I want to have all project dependencies available in the repository,
so that I can build the project without needing an internet connection.

#### Story 2

As a developer, I want to review and audit the dependency code in the `vendor/` directory,
so that I can identify potential security or licensing issues.

### Risks and Mitigations

N/A

## Design Details

The necessary changes to implement this enhancement include:

1. Include all dependant libraries by running `go mod tidy` and `go mod vendor`
to populate `vendor/` directory.
2. Update [Dependabot configuration](https://github.com/zarf-dev/zarf/blob/main/.github/dependabot.yaml)
to [enable support for vendored dependencies](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#vendor--).
3. Modify the [Codeql configuration](https://github.com/zarf-dev/zarf/blob/main/.github/codeql.yaml)
to ignore the `vendor/` directory in scans.
4. Adjust [go mod checker](https://github.com/zarf-dev/zarf/blob/main/.github/workflows/check-go-mod.yml)
to validate the `vendor/` directory instead of solely relying on `go.mod` and
`go.sum` files.

No changes are required to the build process, as the Go compiler [automatically uses](https://go.dev/ref/mod#go-mod-file-go)
the `vendor/` directory if `vendor/modules.txt` is present and consistent with `go.mod`.

## OPEN QUESTION

**What to do with [zarf/hack/schema] sub-project?**

The simplest approach seems to be to leverage the idea of [multi-module workspaces](https://go.dev/doc/tutorial/workspaces)
and implement that instead of maintaining separate `vendor/` directories for each
of the projects.

### Test Plan

[x] I/we understand the owners of the involved components may require updates to
existing tests to make this code solid enough prior to committing the changes necessary
to implement this proposal.

### Graduation Criteria

This feature will be implemented directly in a stable state, as it primarily impacts
the development workflow and poses minimal risk.

### Upgrade / Downgrade Strategy

N/A

### Version Skew Strategy

N/A

## Implementation History

- 2025-01-09: Document created

## Drawbacks

The reasons why this enhancement should not be implemented are presented in the
[Cons](#cons) section, along with explanation how each problem is being addressed.

## Alternatives

Alternative approaches considered for this particular problem included setting
up a cache or mirror. The option was rejected because it requires additional
infrastructure to be built and maintained, as well as adjustments to developer
configurations. Furthermore, it does not align with any of the [goals](#goals).

## Infrastructure Needed (Optional)

N/A
31 changes: 31 additions & 0 deletions 10-vendor-dependencies/zep.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
schema-version: 1.0.0

title: Vendor?
zep-number: 10
authors:
- "@soltysh"
status: implementable
creation-date: 2025-01-09
reviewers:
- "@daveworth"
- "@schristoff"
approvers:
- "@daveworth"
- "@schristoff"

see-also: []
replaces: []

# The target maturity stage in the current dev cycle for this ZEP.
stage: stable

# The most recent milestone for which work toward delivery of this ZEP has been
# done. This can be the current (upcoming) milestone, if it is being actively
# worked on.
latest-milestone: "v0.4x"

# The milestone at which this feature was, or is targeted to be, at each stage.
milestone:
alpha: ""
beta: ""
stable: "v0.4x"