Skip to content

Commit 5d71f0e

Browse files
leodidoona-agent
andcommitted
feat: export SOURCE_DATE_EPOCH for build commands
Export SOURCE_DATE_EPOCH environment variable for all build commands to enable reproducible builds without requiring .git directory. Build commands can use SOURCE_DATE_EPOCH directly for deterministic timestamps. Benefits: - Works in CI environments without full .git history - Standard approach (reproducible-builds.org) - Same timestamp used for tar archives and Docker images - No dependency on git being available Co-authored-by: Ona <no-reply@ona.com>
1 parent 474d783 commit 5d71f0e

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,42 @@ Leeway supports built-in build arguments:
297297
- `__git_commit` contains the current Git commit if the build is executed from within a Git working copy. If this variable is used and the build is not executed from within a Git working copy the variable resolution will fail. If the package sources contain uncommitted files/directories, then `__pkg_version` will be appended to `__git_commit`
298298
- `__git_commit_short` shortened version of `__git_commit` to the first 7 characters.
299299

300+
## Environment Variables
301+
302+
Build commands have access to the following environment variables:
303+
304+
### `SOURCE_DATE_EPOCH`
305+
306+
Unix timestamp for reproducible builds. Contains the git commit timestamp (or value from `SOURCE_DATE_EPOCH` environment variable if set before running leeway).
307+
308+
This enables deterministic timestamps without requiring .git directory, which is useful in CI environments with shallow clones.
309+
310+
**Example usage:**
311+
312+
```yaml
313+
packages:
314+
- name: app
315+
type: go
316+
config:
317+
buildCommand:
318+
- sh
319+
- -c
320+
- |
321+
# SOURCE_DATE_EPOCH is automatically set by leeway
322+
go build -ldflags "-X main.BuildTime=$SOURCE_DATE_EPOCH" -o app
323+
```
324+
325+
**Benefits:**
326+
- Works without .git directory (CI-friendly)
327+
- Standard approach ([reproducible-builds.org](https://reproducible-builds.org/docs/source-date-epoch/))
328+
- Same timestamp used for tar archives and Docker images
329+
330+
**Docker builds:**
331+
332+
For Docker packages, leeway automatically enables BuildKit (`DOCKER_BUILDKIT=1`) and exports `SOURCE_DATE_EPOCH`. For deterministic Docker images, see PR #285 which passes the value as a build arg (requires `ARG SOURCE_DATE_EPOCH` in Dockerfiles).
333+
334+
BuildKit is the default builder since Docker Engine v23.0 and is always used in Docker Desktop.
335+
300336
## Package Variants
301337
Leeway supports build-time variance through "package variants". Those variants are defined on the workspace level and can modify the list of sources, environment variables and config of packages.
302338
For example consider a `WORKSPACE.YAML` with this variants section:

pkg/leeway/build.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,18 @@ func executeCommandsForPackage(buildctx *buildContext, p *Package, wd string, co
25902590

25912591
env := append(os.Environ(), p.Environment...)
25922592
env = append(env, fmt.Sprintf("%s=%s", EnvvarWorkspaceRoot, p.C.W.Origin))
2593+
2594+
// Export SOURCE_DATE_EPOCH for reproducible builds
2595+
// BuildKit (Docker >= v23.0) automatically uses this for deterministic image timestamps
2596+
mtime, err := p.getDeterministicMtime()
2597+
if err == nil {
2598+
env = append(env, fmt.Sprintf("SOURCE_DATE_EPOCH=%d", mtime))
2599+
}
2600+
2601+
// Enable BuildKit to ensure SOURCE_DATE_EPOCH is used for Docker builds
2602+
// BuildKit is default since Docker v23.0, but we set it explicitly for older versions
2603+
env = append(env, "DOCKER_BUILDKIT=1")
2604+
25932605
for _, cmd := range commands {
25942606
if len(cmd) == 0 {
25952607
continue // Skip empty commands

0 commit comments

Comments
 (0)