Skip to content

Commit a089bd1

Browse files
committed
Configure builder by default
1 parent fecb52b commit a089bd1

File tree

7 files changed

+330
-59
lines changed

7 files changed

+330
-59
lines changed

build/env/env.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os/exec"
77
"path/filepath"
88
"strings"
9+
"sync"
910

1011
"github.com/oasisprotocol/cli/cmd/common"
1112
)
@@ -86,6 +87,10 @@ type ContainerEnv struct {
8687
}
8788

8889
var containerCmds = []string{"docker", "podman"}
90+
var (
91+
containerCmdPath string
92+
containerCmdOnce sync.Once
93+
)
8994

9095
// NewContainerEnv creates a new Docker or Podman-based execution environment.
9196
func NewContainerEnv(image, baseDir, dirMount string) *ContainerEnv {
@@ -213,12 +218,20 @@ func (de *ContainerEnv) HasBinary(string) bool {
213218

214219
// getContainerCmd finds a working docker or podman command and returns its path.
215220
func getContainerCmd() string {
216-
for _, cmd := range containerCmds {
217-
if path, err := exec.LookPath(cmd); err == nil && path != "" {
218-
return path
221+
containerCmdOnce.Do(func() {
222+
for _, cmd := range containerCmds {
223+
if path, err := exec.LookPath(cmd); err == nil && path != "" {
224+
containerCmdPath = path
225+
return
226+
}
219227
}
220-
}
221-
return ""
228+
})
229+
return containerCmdPath
230+
}
231+
232+
// IsContainerRuntimeAvailable returns true if a container runtime (docker or podman) is available.
233+
func IsContainerRuntimeAvailable() bool {
234+
return getContainerCmd() != ""
222235
}
223236

224237
// IsAvailable implements ExecEnv.

build/rofl/artifacts.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package rofl
22

3+
// LatestBuilderImage is the latest builder container image to use when building ROFL apps.
4+
const LatestBuilderImage = "ghcr.io/oasisprotocol/rofl-dev:v0.5.0@sha256:31573686552abeb0edebc450f6872831f0006a6cf38220cef7e0789d4376c2c1"
5+
36
// LatestBasicArtifacts are the latest TDX ROFL basic app artifacts.
47
var LatestBasicArtifacts = ArtifactsConfig{
58
Firmware: "https://github.com/oasisprotocol/oasis-boot/releases/download/v0.6.2/ovmf.tdx.fd#db47100a7d6a0c1f6983be224137c3f8d7cb09b63bb1c7a5ee7829d8e994a42f",

build/sgxs/sgxs.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ import (
1515
// It requires the `ftxsgx-elf2sgxs` utility to be installed.
1616
func Elf2Sgxs(buildEnv env.ExecEnv, elfSgxPath, sgxsPath string, heapSize, stackSize, threads uint64) (err error) {
1717
if elfSgxPath, err = buildEnv.PathToEnv(elfSgxPath); err != nil {
18-
return
18+
return err
1919
}
2020
if sgxsPath, err = buildEnv.PathToEnv(sgxsPath); err != nil {
21-
return
21+
return err
2222
}
2323

2424
args := []string{
@@ -31,7 +31,7 @@ func Elf2Sgxs(buildEnv env.ExecEnv, elfSgxPath, sgxsPath string, heapSize, stack
3131

3232
cmd := exec.Command("ftxsgx-elf2sgxs", args...)
3333
if err = buildEnv.WrapCommand(cmd); err != nil {
34-
return
34+
return err
3535
}
3636
if common.IsVerbose() {
3737
fmt.Println(cmd)

cmd/rofl/build/artifacts.go

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"os"
1515
"os/exec"
1616
"path/filepath"
17+
"sort"
1718
"strings"
1819
"time"
1920

@@ -316,13 +317,23 @@ func createSquashFs(buildEnv env.ExecEnv, fn, dir string) (int64, error) {
316317
}
317318

318319
// Create reproducible tar archive.
320+
if os.Getenv("ROFL_DEBUG_ROOTFS_HASH") != "" {
321+
if err := debugRootfsHashes(dir); err != nil {
322+
return 0, fmt.Errorf("failed to compute rootfs debug hashes: %w", err)
323+
}
324+
}
325+
319326
tarPath := fn + ".tar"
327+
tarPathEnv, err := buildEnv.PathToEnv(tarPath)
328+
if err != nil {
329+
return 0, fmt.Errorf("failed to translate tar path for container: %w", err)
330+
}
320331
fmt.Printf("Creating tar archive: %s\n", tarPath)
321332
//nolint:gosec // tarPath is constructed internally, not from user input.
322333
tarCmd := exec.Command(
323334
"tar",
324335
"--create",
325-
"--file="+tarPath,
336+
"--file="+tarPathEnv,
326337
"--format=gnu",
327338
"--sort=name",
328339
"--mtime=@0",
@@ -413,6 +424,69 @@ func createSquashFs(buildEnv env.ExecEnv, fn, dir string) (int64, error) {
413424
return fi.Size(), nil
414425
}
415426

427+
// debugRootfsHashes prints deterministic SHA256 hashes for all files in dir to help diagnose
428+
// cross-host differences. Controlled via ROFL_DEBUG_ROOTFS_HASH env var.
429+
func debugRootfsHashes(dir string) error {
430+
type entry struct {
431+
path string
432+
hash string
433+
}
434+
var entries []entry
435+
436+
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
437+
if err != nil {
438+
return err
439+
}
440+
if d.IsDir() {
441+
return nil
442+
}
443+
rel, err := filepath.Rel(dir, path)
444+
if err != nil {
445+
return err
446+
}
447+
448+
fi, err := os.Lstat(path)
449+
if err != nil {
450+
return err
451+
}
452+
453+
switch {
454+
case fi.Mode()&os.ModeSymlink != 0:
455+
target, err := os.Readlink(path)
456+
if err != nil {
457+
return err
458+
}
459+
entries = append(entries, entry{path: rel, hash: "symlink->" + target})
460+
default:
461+
f, err := os.Open(path)
462+
if err != nil {
463+
return err
464+
}
465+
h := sha256.New()
466+
if _, err = io.Copy(h, f); err != nil {
467+
f.Close()
468+
return err
469+
}
470+
f.Close()
471+
entries = append(entries, entry{path: rel, hash: fmt.Sprintf("%x", h.Sum(nil))})
472+
}
473+
return nil
474+
})
475+
if err != nil {
476+
return err
477+
}
478+
479+
sort.Slice(entries, func(i, j int) bool {
480+
return entries[i].path < entries[j].path
481+
})
482+
483+
fmt.Println("Rootfs file hashes (debug):")
484+
for _, e := range entries {
485+
fmt.Printf(" %s %s\n", e.hash, e.path)
486+
}
487+
return nil
488+
}
489+
416490
// sha256File computes a SHA-256 digest of the file with the given filename and returns a
417491
// hex-encoded hash.
418492
func sha256File(fn string) (string, error) {
@@ -443,17 +517,32 @@ func createVerityHashTree(buildEnv env.ExecEnv, fsFn, hashFn string) (string, er
443517
return "", err
444518
}
445519

520+
// Translate paths for container environments.
521+
fsFnEnv, err := buildEnv.PathToEnv(fsFn)
522+
if err != nil {
523+
return "", fmt.Errorf("failed to translate filesystem path for container: %w", err)
524+
}
525+
526+
hashFnEnv, err := buildEnv.PathToEnv(hashFn)
527+
if err != nil {
528+
return "", fmt.Errorf("failed to translate hash path for container: %w", err)
529+
}
530+
446531
rootHashFn := hashFn + ".roothash"
532+
rootHashFnEnv, err := buildEnv.PathToEnv(rootHashFn)
533+
if err != nil {
534+
return "", fmt.Errorf("failed to translate roothash path for container: %w", err)
535+
}
447536

448537
cmd := exec.Command( //nolint:gosec
449538
veritysetupBin, "format",
450539
"--data-block-size=4096",
451540
"--hash-block-size=4096",
452541
"--uuid=00000000-0000-0000-0000-000000000000",
453542
"--salt="+salt,
454-
"--root-hash-file="+rootHashFn,
455-
fsFn,
456-
hashFn,
543+
"--root-hash-file="+rootHashFnEnv,
544+
fsFnEnv,
545+
hashFnEnv,
457546
)
458547
var out strings.Builder
459548
cmd.Stderr = &out
@@ -556,14 +645,22 @@ func convertToQcow2(buildEnv env.ExecEnv, fn string) error {
556645
}
557646

558647
tmpOutFn := fn + ".qcow2"
648+
fnEnv, err := buildEnv.PathToEnv(fn)
649+
if err != nil {
650+
return fmt.Errorf("failed to translate qcow input path for container: %w", err)
651+
}
652+
tmpOutFnEnv, err := buildEnv.PathToEnv(tmpOutFn)
653+
if err != nil {
654+
return fmt.Errorf("failed to translate qcow output path for container: %w", err)
655+
}
559656

560657
// Execute qemu-img.
561658
cmd := exec.Command(
562659
qemuImgBin,
563660
"convert",
564661
"-O", "qcow2",
565-
fn,
566-
tmpOutFn,
662+
fnEnv,
663+
tmpOutFnEnv,
567664
)
568665
var out strings.Builder
569666
cmd.Stderr = &out

0 commit comments

Comments
 (0)