Skip to content
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
44 changes: 44 additions & 0 deletions build/rofl/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,50 @@ func upgradeArtifacts(upgrade []artifactUpgrade) bool {
return changed
}

// upgradePossible checks if any explicitly configured artifact differs from the latest.
//
// This has intentionally different semantics than upgradeArtifacts:
// - upgradeArtifacts: empty existing + non-empty new -> WRITES the new value
// - upgradePossible: empty existing + non-empty new -> returns FALSE
//
// Rationale: When a manifest field is empty, the build uses the latest defaults
// from code (LatestBasicArtifacts/LatestContainerArtifacts). So an empty field
// means the user is already getting the latest, no notification needed. We only
// notify when explicit overrides exist and are outdated.
func upgradePossible(check []artifactUpgrade) bool {
for _, artifact := range check {
if artifact.new == "" {
continue
}
if *artifact.existing != "" && *artifact.existing != artifact.new {
return true
}
}
return false
}

// UpgradePossible returns true iff any explicitly set artifacts differ from latest.
// Empty fields are ignored (they use defaults from code, so already latest).
func (ac *ArtifactsConfig) UpgradePossible(latest *ArtifactsConfig) bool {
if upgradePossible([]artifactUpgrade{
{&ac.Builder, latest.Builder},
{&ac.Firmware, latest.Firmware},
{&ac.Kernel, latest.Kernel},
{&ac.Stage2, latest.Stage2},
}) {
return true
}
return ac.Container.UpgradePossible(&latest.Container)
}

// UpgradePossible returns true iff any explicitly set container artifacts differ from latest.
func (cc *ContainerArtifactsConfig) UpgradePossible(latest *ContainerArtifactsConfig) bool {
return upgradePossible([]artifactUpgrade{
{&cc.Compose, latest.Compose},
{&cc.Runtime, latest.Runtime},
})
}

// UpgradeTo upgrades the artifacts to the latest version by updating any relevant fields.
//
// Returns true iff any artifacts have been updated.
Expand Down
52 changes: 52 additions & 0 deletions build/rofl/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,55 @@ func TestUpgradeArtifacts(t *testing.T) {
changed = existing.UpgradeTo(&latest)
require.False(changed)
}

func TestUpgradePossible(t *testing.T) {
require := require.New(t)

existing := ArtifactsConfig{
Builder: "a",
Firmware: "b",
Kernel: "c",
Stage2: "d",
Container: ContainerArtifactsConfig{
Runtime: "e",
Compose: "f",
},
}
latest := ArtifactsConfig{
Firmware: "b2",
Kernel: "c2",
Stage2: "d2",
Container: ContainerArtifactsConfig{
Runtime: "e2",
},
}

// Explicit overrides differing from latest -> upgradeable.
require.True(existing.UpgradePossible(&latest))

// After upgrading -> not upgradeable.
existing.UpgradeTo(&latest)
require.False(existing.UpgradePossible(&latest))

// Empty config (uses defaults from code) -> not upgradeable.
require.False((&ArtifactsConfig{}).UpgradePossible(&latest))

// Partial: explicit override differs -> upgradeable.
require.True((&ArtifactsConfig{Firmware: "old"}).UpgradePossible(&latest))

// Partial: explicit override matches latest -> not upgradeable.
require.False((&ArtifactsConfig{Firmware: "b2"}).UpgradePossible(&latest))

// Container field differs -> upgradeable.
require.True((&ArtifactsConfig{
Container: ContainerArtifactsConfig{Runtime: "old"},
}).UpgradePossible(&ArtifactsConfig{
Container: ContainerArtifactsConfig{Runtime: "new"},
}))

// ContainerArtifactsConfig directly.
containerLatest := ContainerArtifactsConfig{Runtime: "new"}
require.True((&ContainerArtifactsConfig{Runtime: "old"}).UpgradePossible(&containerLatest))
require.False((&ContainerArtifactsConfig{Runtime: "new"}).UpgradePossible(&containerLatest))
require.False((&ContainerArtifactsConfig{}).UpgradePossible(&containerLatest))
}
38 changes: 38 additions & 0 deletions cmd/rofl/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ var (

fmt.Println("Manifest enclave identities MATCH on-chain enclave identities.")
}

// Check if artifact upgrades are available and notify the user.
notifyUpgradeAvailable(manifest)

return nil
}

Expand Down Expand Up @@ -332,11 +336,45 @@ var (

fmt.Printf("Run `oasis rofl update` to update your ROFL app's on-chain configuration.\n")
}

// Check if artifact upgrades are available and notify the user.
notifyUpgradeAvailable(manifest)

return nil
},
}
)

// notifyUpgradeAvailable checks if artifact upgrades are available and prints a notification.
func notifyUpgradeAvailable(manifest *buildRofl.Manifest) {
var latestArtifacts buildRofl.ArtifactsConfig
switch manifest.TEE {
case buildRofl.TEETypeTDX:
switch manifest.Kind {
case buildRofl.AppKindRaw:
latestArtifacts = buildRofl.LatestBasicArtifacts
latestArtifacts.Builder = buildRofl.LatestBuilderImage
case buildRofl.AppKindContainer:
latestArtifacts = buildRofl.LatestContainerArtifacts
latestArtifacts.Builder = buildRofl.LatestContainerBuilderImage
default:
return
}
default:
return
}

current := manifest.Artifacts
if current == nil {
current = &buildRofl.ArtifactsConfig{}
}

if current.UpgradePossible(&latestArtifacts) {
fmt.Println()
fmt.Println("NOTE: A new version of artifacts is available. Run `oasis rofl upgrade` to upgrade.")
}
}

// setupContainerEnv creates and initializes a container build environment.
func setupContainerEnv(builderImage string) (env.ExecEnv, error) {
baseDir, err := env.GetBasedir()
Expand Down
3 changes: 2 additions & 1 deletion cmd/rofl/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,8 @@ var (
}

if artifactsUpdated {
fmt.Printf("Run `oasis rofl build` to build your ROFL app.\n")
fmt.Printf("Artifacts have been updated to the latest versions.\n")
fmt.Printf("Run `oasis rofl build` to build with the new artifacts.\n")
} else {
fmt.Printf("Artifacts already up-to-date.\n")
}
Expand Down
2 changes: 1 addition & 1 deletion examples/rofl/upgrade.in.static
Original file line number Diff line number Diff line change
@@ -1 +1 @@
oasis rofl upgrade
oasis rofl upgrade
2 changes: 2 additions & 0 deletions examples/rofl/upgrade.out.static
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Artifacts have been updated to the latest versions.
Run `oasis rofl build` to build with the new artifacts.