Skip to content
15 changes: 13 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,18 @@ require (
require (
github.com/distribution/reference v0.6.0
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
github.com/moby/moby/client v0.5.0
github.com/modelcontextprotocol/go-sdk v1.7.0
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/tmc/go-iroh v0.2.2
)

require (
filippo.io/edwards25519 v1.2.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/coder/websocket v1.8.14 // indirect
github.com/containerd/console v1.0.5 // indirect
github.com/containerd/containerd/api v1.10.0 // indirect
Expand All @@ -49,9 +52,11 @@ require (
github.com/containerd/platforms v1.0.0-rc.4 // indirect
github.com/containerd/ttrpc v1.2.8 // indirect
github.com/containerd/typeurl/v2 v2.3.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.8 // indirect
github.com/docker/go-connections v0.7.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fvbommel/sortorder v1.2.0 // indirect
github.com/go-openapi/swag/cmdutils v0.26.0 // indirect
github.com/go-openapi/swag/conv v0.26.0 // indirect
github.com/go-openapi/swag/fileutils v0.26.0 // indirect
Expand All @@ -66,6 +71,7 @@ require (
github.com/gofrs/flock v0.13.0 // indirect
github.com/google/jsonschema-go v0.4.3 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/in-toto/attestation v1.2.0 // indirect
github.com/in-toto/in-toto-golang v0.11.0 // indirect
Expand All @@ -74,12 +80,16 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.22 // indirect
github.com/mattn/go-runewidth v0.0.24 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/moby/api v1.55.0 // indirect
github.com/moby/patternmatcher v0.6.1 // indirect
github.com/moby/spdystream v0.5.1 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/moby/sys/sequential v0.7.0 // indirect
github.com/moby/sys/signal v0.7.1 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
Expand All @@ -96,7 +106,8 @@ require (
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.69.0 // indirect
gotest.tools/v3 v3.5.2 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.45.0 // indirect
k8s.io/streaming v0.36.1 // indirect
lukechampine.com/blake3 v1.4.1 // indirect
)
Expand Down Expand Up @@ -137,7 +148,7 @@ require (
github.com/prometheus/common v0.67.5 // indirect
github.com/prometheus/procfs v0.20.1 // indirect
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10 // indirect
github.com/spf13/pflag v1.0.10
github.com/x448/float16 v0.8.4 // indirect
go.miloapis.com/service-catalog v0.10.0
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
Expand Down
23 changes: 23 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1x
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
Expand Down Expand Up @@ -82,12 +84,16 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v29.5.3+incompatible h1:nbEFfz774vBwQ5KRYv7c/AghjReqnGISvrRhzjV0evs=
github.com/docker/cli v29.5.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.8 h1:bIREROb7So6PRlq6KTtdS9MPEjC29OQRkFNlvK2OX8Q=
github.com/docker/docker-credential-helpers v0.9.8/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c=
github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
Expand All @@ -104,6 +110,8 @@ github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeO
github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE=
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/fvbommel/sortorder v1.2.0 h1:TRIiRiGX+djh3Yf4FVxmWmAcYfIr5dH0NbzJWOSAWZk=
github.com/fvbommel/sortorder v1.2.0/go.mod h1:LbhO04ijZIeUuvz9B9BkI/qYrpZZEn1gWhxv4QjUKVs=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=
Expand Down Expand Up @@ -186,6 +194,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
Expand Down Expand Up @@ -220,6 +230,8 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
github.com/moby/buildkit v0.31.1 h1:j3p55abBl4kiXXPZgYX+6zWgB2aefqHXoPown12fIzU=
Expand All @@ -228,6 +240,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/moby/api v1.55.0 h1:2/sexvQyqIWS8pRSCFddBfpW2qE7vR7FCL+vN8pxwMc=
github.com/moby/moby/api v1.55.0/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
github.com/moby/moby/client v0.5.0 h1:5XhyPk2fuOWf6RlSFa3MkIIgDZkF25xToXW8Q/BH7cc=
github.com/moby/moby/client v0.5.0/go.mod h1:rcVpF8ncl9vo5gaIBdol6CnbEtSj1uxMvEV/UrykF/s=
github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U=
github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/policy-helpers v0.0.0-20260612073044-d5411a945cfc h1:dvhPFj1niuMP3CBCjhiZWJQr//+w1LOA8cHclFJnNe0=
Expand Down Expand Up @@ -377,6 +393,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU=
go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0 h1:SUplec5dp06reu1zaXmOXdvqH398taqrDXqUl99jxSc=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0/go.mod h1:ho2g4N+ane+swq5I/VBkKWnRDY4kUINH3FuqyZqX/Ug=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0 h1:QRefszxJmfPdjXUUm3j6iDzY03mTPXMjqErFqQ67vUg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0/go.mod h1:Tiz03lTBVBrm7eWZBOidzEaYaJa8tjwGUGv6d8mlTyk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww=
Expand All @@ -385,6 +403,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 h1:lgh3P
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0/go.mod h1:5Cnhth3m/AgOeTgE3ex12pPmiu/gGtZit03kSzx9X7s=
go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M=
go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s=
go.opentelemetry.io/otel/metric/x v0.67.0 h1:PcicCNZFkZ4bXfSooXdo3WN7RBOVOtjVdo1wD358Uns=
go.opentelemetry.io/otel/metric/x v0.67.0/go.mod h1:FBjCWZe6wgcqxcMtjdGiClDKXb2YxxXii0CXftE4QtI=
go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw=
go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA=
go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o=
Expand Down Expand Up @@ -418,6 +438,7 @@ golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
Expand Down Expand Up @@ -472,6 +493,8 @@ lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
mvdan.cc/sh/v3 v3.12.0 h1:ejKUR7ONP5bb+UGHGEG/k9V5+pRVIyD+LsZz7o8KHrI=
mvdan.cc/sh/v3 v3.12.0/go.mod h1:Se6Cj17eYSn+sNooLZiEUnNNmNxg0imoYlTu4CyaGyg=
pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
Expand Down
9 changes: 5 additions & 4 deletions internal/cmd/compute/build/analysis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1003,10 +1003,11 @@ func TestRootfsBuildError(t *testing.T) {
}{
{name: "keeps Dockerfile build failures as-is",
input: `process "/bin/sh -c go build ./..." did not complete successfully: exit code: 1`,
wantIn: "go build", wantNotIn: "Docker is not running"},
{name: "simplifies Docker availability failures",
input: "could not connect to buildkit: could not start ephemeral BuildKit container",
want: "building root filesystem: Docker is not running or is not accessible"},
wantIn: "go build"},
{name: "explains a missing credential helper",
input: `failed to solve: error getting credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH, out: ` + "``",
wantIn: `can't be read, so your Dockerfile's base images can't be pulled.` + "\n\n" +
`Your Docker config says sign-ins are stored by "desktop"`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
93 changes: 32 additions & 61 deletions internal/cmd/compute/build/buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,16 @@ import (
"path"
"path/filepath"
"strings"
"time"

"github.com/docker/cli/cli/config"
dockerclient "github.com/docker/docker/client"
dockerbuildkit "github.com/docker/docker/client/buildkit"
erofs "github.com/erofs/go-erofs"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/types"
bkclient "github.com/moby/buildkit/client"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/auth/authprovider"
bkappdefaults "github.com/moby/buildkit/util/appdefaults"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/tonistiigi/fsutil"
"golang.org/x/sync/errgroup"
Expand All @@ -44,6 +42,7 @@ type buildRequest struct {
}

type dockerfileFinalStageRequest struct {
Address string
ContextDir string
Dockerfile string
Target string
Expand All @@ -55,6 +54,7 @@ type dockerfileFinalStageRequest struct {

func buildDockerfileFinalStage(ctx context.Context, req dockerfileFinalStageRequest) (packagingArtifact, error) {
if err := buildDockerfileExports(ctx, buildRequest{
Address: req.Address,
ContextDir: req.ContextDir,
Dockerfile: req.Dockerfile,
Target: req.Target,
Expand Down Expand Up @@ -91,7 +91,11 @@ func buildDockerfileFinalStage(ctx context.Context, req dockerfileFinalStageRequ
return packagingArtifact{Path: req.RootFSTar, Config: config}, nil
}

func createErofsFromTar(tarPath, output string) error {
// createErofsFromTar packs a rootfs tar into an EROFS image. The image's
// build time is fixed so identical input gives identical bytes; with epoch
// set, file times are also clamped to it (SOURCE_DATE_EPOCH semantics), so
// rebuilds that only touched timestamps match too.
func createErofsFromTar(tarPath, output string, epoch *time.Time) error {
out, err := os.OpenFile(output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)
if err != nil {
return fmt.Errorf("creating EROFS image: %w", err)
Expand All @@ -110,7 +114,11 @@ func createErofsFromTar(tarPath, output string) error {
}
defer os.RemoveAll(tempDir)

w := erofs.Create(out, erofs.WithTempDir(tempDir))
var buildTime uint64
if epoch != nil {
buildTime = uint64(epoch.Unix())
}
w := erofs.Create(out, erofs.WithTempDir(tempDir), erofs.WithBuildTime(buildTime, 0))
regularFiles := make(map[string]string)
tr := tar.NewReader(in)
for {
Expand All @@ -121,12 +129,23 @@ func createErofsFromTar(tarPath, output string) error {
if err != nil {
return fmt.Errorf("reading rootfs tar: %w", err)
}
if epoch != nil {
hdr.ModTime = clampTime(hdr.ModTime, *epoch)
hdr.AccessTime = clampTime(hdr.AccessTime, *epoch)
}
if err := addTarEntryToErofs(w, tempDir, regularFiles, tr, hdr); err != nil {
return err
}
}
}

func clampTime(t, limit time.Time) time.Time {
if t.After(limit) {
return limit
}
return t
}

func addTarEntryToErofs(w *erofs.Writer, tempDir string, regularFiles map[string]string, tr *tar.Reader, hdr *tar.Header) error {
name, err := safeRootfsTarPath(hdr.Name)
if err != nil {
Expand Down Expand Up @@ -282,14 +301,17 @@ func firstImageFromIndex(idx v1.ImageIndex) (v1.Image, error) {
}

func buildDockerfileExports(ctx context.Context, req buildRequest, rootfsTarPath string, ociTarPath string) error {
bk, cleanup, err := connectBuildkit(ctx, req.Address)
bk, cleanup, endpoint, err := connectBuildkit(ctx, req.Address)
if err != nil {
return err
}
defer bk.Close()
if cleanup != nil {
defer cleanup()
}
if req.progressOut != nil {
fmt.Fprintf(req.progressOut, "Building with %s\n", endpoint)
}

rootfsTar, err := os.OpenFile(rootfsTarPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644)
if err != nil {
Expand Down Expand Up @@ -357,61 +379,6 @@ func closeExportFile(f *os.File) error {
return err
}

func connectBuildkit(ctx context.Context, address string) (*bkclient.Client, func(), error) {
if address == "" {
address = os.Getenv("BUILDKIT_HOST")
}
if address != "" {
c, err := bkclient.New(ctx, address)
if err != nil {
return nil, nil, fmt.Errorf("creating configured BuildKit client: %w", err)
}
if _, err := c.Info(ctx); err != nil {
_ = c.Close()
return nil, nil, fmt.Errorf("connecting to configured BuildKit client: %w", err)
}
return c, nil, nil
}

if c, err := bkclient.New(ctx, bkappdefaults.Address); err == nil {
if _, err := c.Info(ctx); err == nil {
return c, nil, nil
}
_ = c.Close()
}

c, cleanup, err := connectDockerBuildkit(ctx)
if err == nil && c != nil {
return c, cleanup, nil
}
if err != nil {
return nil, nil, err
}
return nil, nil, fmt.Errorf("could not connect to BuildKit: set BUILDKIT_HOST, start buildkitd, or enable Docker's BuildKit backend")
}

func connectDockerBuildkit(ctx context.Context) (*bkclient.Client, func(), error) {
docker, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
if err != nil {
return nil, nil, nil
}
if _, err := docker.ServerVersion(ctx); err != nil {
_ = docker.Close()
return nil, nil, nil
}
c, err := bkclient.New(ctx, "", dockerbuildkit.ClientOpts(docker)...)
if err != nil {
_ = docker.Close()
return nil, nil, fmt.Errorf("creating Docker BuildKit client: %w", err)
}
if _, err := c.Info(ctx); err != nil {
_ = c.Close()
_ = docker.Close()
return nil, nil, nil
}
return c, func() { _ = docker.Close() }, nil
}

func buildSolveOpt(req buildRequest, output io.WriteCloser) (*bkclient.SolveOpt, error) {
contextMount, err := fsutil.NewFS(req.ContextDir)
if err != nil {
Expand All @@ -429,6 +396,10 @@ func buildSolveOpt(req buildRequest, output io.WriteCloser) (*bkclient.SolveOpt,
if req.Target != "" {
attrs["target"] = req.Target
}
if epoch := os.Getenv(sourceDateEpochEnv); epoch != "" {
// Like docker buildx; an explicit --build-arg below still wins.
attrs["build-arg:"+sourceDateEpochEnv] = epoch
}
for _, arg := range req.BuildArgs {
key, value, ok := strings.Cut(arg, "=")
if key == "" {
Expand Down
Loading
Loading