Skip to content

Commit

Permalink
MountStubsCleaner: preserve timestamps
Browse files Browse the repository at this point in the history
Fix issue 3148

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
  • Loading branch information
AkihiroSuda committed Oct 5, 2022
1 parent 092e977 commit 7f5cfe4
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
56 changes: 56 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ func TestIntegration(t *testing.T) {
testExportAnnotationsMediaTypes,
testExportAttestations,
testAttestationDefaultSubject,
testMountStubsTimestamp,
)
tests = append(tests, diffOpTestCases()...)
integration.Run(t, tests, mirrors)
Expand Down Expand Up @@ -6769,6 +6770,61 @@ func testAttestationDefaultSubject(t *testing.T, sb integration.Sandbox) {
}
}

// https://github.com/moby/buildkit/issues/3148
func testMountStubsTimestamp(t *testing.T, sb integration.Sandbox) {
c, err := New(sb.Context(), sb.Address())
require.NoError(t, err)
defer c.Close()

const sourceDateEpoch = int64(1234567890) // Fri Feb 13 11:31:30 PM UTC 2009
st := llb.Image("busybox:latest").Run(
llb.Args([]string{"/bin/touch", fmt.Sprintf("--date=@%d", sourceDateEpoch), "/bin", "/etc"}),
)
def, err := st.Marshal(sb.Context())
require.NoError(t, err)

tmpDir := t.TempDir()
tarFile := filepath.Join(tmpDir, "out.tar")
tarFileW, err := os.Create(tarFile)
require.NoError(t, err)
defer tarFileW.Close()

_, err = c.Solve(sb.Context(), def, SolveOpt{
Exports: []ExportEntry{
{
Type: ExporterTar,
Output: fixedWriteCloser(tarFileW),
},
},
}, nil)
require.NoError(t, err)
tarFileW.Close()

tarFileR, err := os.Open(tarFile)
require.NoError(t, err)
defer tarFileR.Close()
tarR := tar.NewReader(tarFileR)
touched := map[string]*tar.Header{
"bin/": nil,
"etc/": nil,
}
for {
hd, err := tarR.Next()
if errors.Is(err, io.EOF) {
break
}
require.NoError(t, err)
if x, ok := touched[hd.Name]; ok && x == nil {
touched[hd.Name] = hd
}
}
for name, hd := range touched {
t.Logf("Verifying %q (%+v)", name, hd)
require.NotNil(t, hd, name)
require.Equal(t, sourceDateEpoch, hd.ModTime.Unix(), name)
}
}

func makeSSHAgentSock(t *testing.T, agent agent.Agent) (p string, err error) {
tmpDir, err := integration.Tmpdir(t)
if err != nil {
Expand Down
22 changes: 21 additions & 1 deletion executor/stubs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"syscall"

"github.com/containerd/continuity/fs"
"github.com/sirupsen/logrus"
)

func MountStubsCleaner(dir string, mounts []Mount) func() {
Expand Down Expand Up @@ -43,7 +44,26 @@ func MountStubsCleaner(dir string, mounts []Mount) func() {
if st.Size() != 0 {
continue
}
os.Remove(p)
// Back up the timestamps of the dir for reproducible builds
// https://github.com/moby/buildkit/issues/3148
dir := filepath.Dir(p)
dirSt, err := os.Stat(dir)
if err != nil {
logrus.WithError(err).Warnf("Failed to stat %q (parent of %q)", dir, p)
continue
}
atime := fs.StatATimeAsTime(dirSt.Sys().(*syscall.Stat_t))
mtime := dirSt.ModTime()

if err := os.RemoveAll(p); err != nil {
logrus.WithError(err).Warnf("Failed to remove %q", p)
continue
}

// Revert the timestamps of the dir
if err := os.Chtimes(dir, atime, mtime); err != nil {
logrus.WithError(err).Warnf("Failed to os.Chtimes(%q, %v, %v)", dir, atime, mtime)
}
}
}
}

0 comments on commit 7f5cfe4

Please sign in to comment.