Skip to content

Commit

Permalink
STONEBLD-1954 assign each build attempt a unique ID
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed Nov 20, 2023
1 parent fb4b3f6 commit 997e6f0
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 51 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/CycloneDX/cyclonedx-go v0.7.1
github.com/aws/aws-sdk-go v1.46.2
github.com/google/go-containerregistry v0.15.2
github.com/google/uuid v1.3.0
github.com/redhat-appstudio/image-controller v0.0.0-20231003082540-48893226ba8b
github.com/tektoncd/cli v0.31.1
go.uber.org/zap v1.24.0
Expand Down Expand Up @@ -70,7 +71,6 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 // indirect
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class ContainerTagCommand implements Runnable {
@CommandLine.Option(names = "--registry-prepend-tag", defaultValue = "")
String prependTag;

@CommandLine.Option(names = "--image-id", required = true)
String imageId;
@CommandLine.Option(names = "--image-digest", required = true)
String imageDigest;

@CommandLine.Parameters(split = ",")
List<String> gavs;
Expand All @@ -41,9 +41,9 @@ public void run() {

ContainerRegistryDeployer deployer = new ContainerRegistryDeployer(host, port, owner, token.orElse(""), repository,
insecure,
prependTag, imageId);
prependTag);
try {
deployer.tagArchive(gavs);
deployer.tagArchive(imageDigest, gavs);
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class DeployCommand implements Runnable {
private static final String DOT_POM = ".pom";
private static final String DOT = ".";
private static final Set<String> ALLOWED_CONTAMINANTS = Set.of("-tests.jar");
public static final String IMAGE_DIGEST_OUTPUT = "Image Digest: ";
final BeanManager beanManager;
final ResultsUpdater resultsUpdater;

Expand Down Expand Up @@ -133,6 +134,8 @@ public class DeployCommand implements Runnable {
@CommandLine.Option(names = "--git-identity")
String gitIdentity;

@CommandLine.Option(names = "--build-id")
String buildId;
// Testing only ; used to disable image deployment
protected boolean imageDeployment = true;

Expand Down Expand Up @@ -214,7 +217,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
+ gav.getVersion(),
"rebuilt",
Map.of("scm-uri", scmUri, "scm-commit", commit, "hermetic",
Boolean.toString(hermetic))),
Boolean.toString(hermetic), "build-id", buildId)),
Files.newOutputStream(temp), false);
Files.delete(file);
Files.move(temp, file);
Expand Down Expand Up @@ -305,6 +308,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
} else {
Log.errorf("Skipped deploying from task run %s as all artifacts were contaminated", taskRun);
}
if (imageDigest != null) {
System.out.println(IMAGE_DIGEST_OUTPUT + "sha256:" + imageDigest);
}
if (taskRun != null) {

List<Contaminates> newContaminates = new ArrayList<>();
Expand Down Expand Up @@ -383,15 +389,15 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th
protected void doDeployment(Path sourcePath, Path logsPath, Set<String> gavs) throws Exception {
if (imageDeployment) {
ContainerRegistryDeployer deployer = new ContainerRegistryDeployer(host, port, owner, token.orElse(""), repository,
insecure, prependTag,
imageId);
deployer.deployArchive(deploymentPath, sourcePath, logsPath, gavs, new BiConsumer<String, String>() {
@Override
public void accept(String s, String hash) {
imageName = s;
imageDigest = hash;
}
});
insecure, prependTag);
deployer.deployArchive(deploymentPath, sourcePath, logsPath, gavs, imageId, buildId,
new BiConsumer<String, String>() {
@Override
public void accept(String s, String hash) {
imageName = s;
imageDigest = hash;
}
});
}
if (isNotEmpty(mvnRepo)) {
// Maven Repo Deployment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class DeployHermeticPreBuildImageCommand implements Runnable {
public void run() {
ContainerRegistryDeployer deployer = new ContainerRegistryDeployer(host, port, owner, token.orElse(""), repository,
insecure,
prependTag, "");
prependTag);
try {
deployer.deployHermeticPreBuildImage(builderImage, buildArtifactsPath, repositoryPath, imageSourcePath, imageName,
new BiConsumer<String, String>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class DeployPreBuildImageCommand implements Runnable {
public void run() {
ContainerRegistryDeployer deployer = new ContainerRegistryDeployer(host, port, owner, token.orElse(""), repository,
insecure,
prependTag, "");
prependTag);
try {
deployer.deployPreBuildImage(builderImage, sourcePath, imageSourcePath, imageName,
new BiConsumer<String, String>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
Expand Down Expand Up @@ -56,16 +55,14 @@ public class ContainerRegistryDeployer {

private final Credential credential;

final String imageId;

public ContainerRegistryDeployer(
String host,
int port,
String owner,
String token,
String repository,
boolean insecure,
String prependTag, String imageId) {
String prependTag) {
if (insecure) {
System.setProperty("sendCredentialsOverHttp", "true");
}
Expand All @@ -76,7 +73,6 @@ public ContainerRegistryDeployer(
this.repository = repository;
this.insecure = insecure;
this.prependTag = prependTag;
this.imageId = imageId;
String fullName = host + (port == 443 ? "" : ":" + port) + "/" + owner + "/" + repository;
this.credential = ContainerUtil.processToken(fullName, token);

Expand All @@ -86,18 +82,18 @@ public ContainerRegistryDeployer(
Log.infof("Prepend tag is %s", prependTag);
}

public void deployArchive(Path deployDir, Path sourcePath, Path logsPath, Set<String> gavs,
public void deployArchive(Path deployDir, Path sourcePath, Path logsPath, Set<String> gavs, String imageId, String buildId,
BiConsumer<String, String> imageNameHashCallback) throws Exception {
Log.debugf("Using Container registry %s:%d/%s/%s", host, port, owner, repository);

// Read the tar to get the gavs and files
DeployData imageData = new DeployData(deployDir, gavs);

// Create the image layers
createImages(imageData, sourcePath, logsPath, imageNameHashCallback);
createImages(imageData, sourcePath, logsPath, imageId, buildId, imageNameHashCallback);
}

public void tagArchive(List<String> gavNames) throws Exception {
public void tagArchive(String imageDigest, List<String> gavNames) throws Exception {
if (gavNames.isEmpty()) {
throw new RuntimeException("Empty GAV list");
}
Expand All @@ -107,7 +103,7 @@ public void tagArchive(List<String> gavNames) throws Exception {
gavs.push(Gav.parse(i));
}
Gav first = gavs.pop();
String existingImage = createImageName(imageId);
String existingImage = createImageNameFromDigest(imageDigest);
RegistryImage existingRegistryImage = RegistryImage.named(existingImage);
RegistryImage registryImage = RegistryImage.named(createImageName(first.getTag()));
if (credential != null) {
Expand Down Expand Up @@ -221,17 +217,18 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
}

private void createImages(DeployData imageData, Path sourcePath, Path logsPath,
BiConsumer<String, String> imageNameHashCallback)
String imageId, String buildId, BiConsumer<String, String> imageNameHashCallback)
throws InvalidImageReferenceException, InterruptedException, RegistryException, IOException,
CacheDirectoryCreationException, ExecutionException {

String imageName = createImageName();
String imageName = createImageName(buildId);
RegistryImage registryImage = RegistryImage.named(imageName);
if (credential != null) {
registryImage = registryImage.addCredentialRetriever(() -> Optional.of(credential));
}
Containerizer containerizer = Containerizer
.to(registryImage)
.withAdditionalTag(imageId)
.setAllowInsecureRegistries(insecure);
Log.infof("Deploying base image %s", imageName);

Expand Down Expand Up @@ -260,11 +257,6 @@ private void createImages(DeployData imageData, Path sourcePath, Path logsPath,
}
}

private String createImageName() {
String tag = imageId == null ? UUID.randomUUID().toString() : imageId;
return createImageName(tag);
}

private String createImageName(String tag) {
// As the tests utilise prependTag for uniqueness so check for that
// here to avoid reusing images when we want differentiation.
Expand All @@ -284,6 +276,15 @@ private String createImageName(String tag) {
+ ":" + tag;
}

private String createImageNameFromDigest(String digest) {
if (port == 443) {
return host + "/" + owner + "/" + repository
+ "@" + digest;
}
return host + ":" + port + "/" + owner + "/" + repository
+ "@" + digest;
}

private List<Path> getLayers(Path artifacts, Path source, Path logs) {
Log.debug("\n Container details:\n"
+ "\t layer 1 (source) " + source.toString() + "\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
Expand Down Expand Up @@ -81,6 +83,7 @@ public void testDeployArchive(QuarkusMainLauncher launcher) throws IOException {
"--image-id=test-image",
"--registry-host=" + container.getHost(),
"--registry-port=" + port,
"--build-id=test-id",
"--registry-owner=" + OWNER,
"--registry-repository=" + REPOSITORY,
"--source-path=" + source.toAbsolutePath().toString(),
Expand All @@ -92,18 +95,24 @@ public void testDeployArchive(QuarkusMainLauncher launcher) throws IOException {
Assertions.assertEquals(0, result.exitCode());
// Now we validate that the image and tags exist in the registry
ContainerRegistryDetails containerRegistryDetails = getContainerRegistryDetails();

Assertions.assertTrue(containerRegistryDetails.repoName.startsWith(OWNER + "/" + REPOSITORY));
Assertions.assertTrue(containerRegistryDetails.tags.contains("test-image"));
Assertions.assertTrue(containerRegistryDetails.tags.contains("test-id"));
Assertions.assertFalse(containerRegistryDetails.tags.contains(EXPECTED_TAG_1));
Assertions.assertFalse(containerRegistryDetails.tags.contains(EXPECTED_TAG_2));
System.out.println(result.getOutput());
Pattern p = Pattern.compile(DeployCommand.IMAGE_DIGEST_OUTPUT + "(.*)");
Matcher matcher = p.matcher(result.getOutput());
Assertions.assertTrue(matcher.find());
String digest = matcher.group(1);

result = launcher.launch("tag-container",
"--registry-host=" + container.getHost(),
"--registry-port=" + port,
"--registry-owner=" + OWNER,
"--registry-repository=" + REPOSITORY,
"--registry-insecure",
"--image-id=test-image",
"--image-digest=" + digest,
GROUP + ":" + FOO_BAR + ":" + VERSION + "," + GROUP + ":" + FOO_BAZ + ":" + VERSION);
containerRegistryDetails = getContainerRegistryDetails();
Assertions.assertTrue(containerRegistryDetails.tags.contains(EXPECTED_TAG_1));
Expand Down Expand Up @@ -184,6 +193,7 @@ private URL getRegistryURL(String path) throws IOException {

class ContainerRegistryDetails {
String repoName;
String digest;
List<String> tags;
}
}
5 changes: 3 additions & 2 deletions pkg/apis/jvmbuildservice/v1alpha1/dependencybuild_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ type DependencyBuildList struct {
}

type BuildAttempt struct {
Recipe *BuildRecipe `json:"buildRecipe,omitempty"`
Build *BuildPipelineRun `json:"build,omitempty"`
BuildId string `json:"buildId,omitempty"`
Recipe *BuildRecipe `json:"buildRecipe,omitempty"`
Build *BuildPipelineRun `json:"build,omitempty"`
}

type BuildPipelineRun struct {
Expand Down
24 changes: 11 additions & 13 deletions pkg/reconciler/dependencybuild/buildrecipeyaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
MavenArtifactsPath = "/maven-artifacts"
PreBuildImageDigest = "PRE_BUILD_IMAGE_DIGEST"
HermeticPreBuildImageDigest = "HERMETIC_PRE_BUILD_IMAGE_DIGEST"
DeployedImageDigest = "DEPLOYED_IMAGE_DIGEST"
)

//go:embed scripts/maven-build.sh
Expand Down Expand Up @@ -53,7 +54,7 @@ var buildEntryScript string
//go:embed scripts/hermetic-entry.sh
var hermeticBuildEntryScript string

func createPipelineSpec(tool string, commitTime int64, jbsConfig *v1alpha12.JBSConfig, systemConfig *v1alpha12.SystemConfig, recipe *v1alpha12.BuildRecipe, db *v1alpha12.DependencyBuild, paramValues []pipelinev1beta1.Param, buildRequestProcessorImage string) (*pipelinev1beta1.PipelineSpec, string, error) {
func createPipelineSpec(tool string, commitTime int64, jbsConfig *v1alpha12.JBSConfig, systemConfig *v1alpha12.SystemConfig, recipe *v1alpha12.BuildRecipe, db *v1alpha12.DependencyBuild, paramValues []pipelinev1beta1.Param, buildRequestProcessorImage string, buildId string) (*pipelinev1beta1.PipelineSpec, string, error) {

// Rather than tagging with hash of json build recipe, buildrequestprocessor image and db.Name as the former two
// could change with new image versions just use db.Name (which is a hash of scm url/tag/path so should be stable)
Expand All @@ -62,7 +63,7 @@ func createPipelineSpec(tool string, commitTime int64, jbsConfig *v1alpha12.JBSC
hermeticBuildRequired := jbsConfig.Spec.HermeticBuilds == v1alpha12.HermeticBuildTypeRequired
verifyBuiltArtifactsArgs := verifyParameters(jbsConfig, recipe)

preBuildImageArgs, deployArgs, hermeticDeployArgs, tagArgs, createHermeticImageArgs := imageRegistryCommands(imageId, recipe, db, jbsConfig, hermeticBuildRequired)
preBuildImageArgs, deployArgs, hermeticDeployArgs, tagArgs, createHermeticImageArgs := imageRegistryCommands(imageId, recipe, db, jbsConfig, hermeticBuildRequired, buildId)
gitArgs := gitArgs(db, recipe)
install := additionalPackages(recipe)

Expand Down Expand Up @@ -331,7 +332,7 @@ func createPipelineSpec(tool string, commitTime int64, jbsConfig *v1alpha12.JBSC
}
tagTask := pipelinev1beta1.TaskSpec{
Workspaces: []pipelinev1beta1.WorkspaceDeclaration{{Name: WorkspaceBuildSettings}, {Name: WorkspaceSource}, {Name: WorkspaceTls}},
Params: []pipelinev1beta1.ParamSpec{{Name: "GAVS", Type: pipelinev1beta1.ParamTypeString}},
Params: []pipelinev1beta1.ParamSpec{{Name: "GAVS", Type: pipelinev1beta1.ParamTypeString}, {Name: DeployedImageDigest, Type: pipelinev1beta1.ParamTypeString}},
Steps: []pipelinev1beta1.Step{
{
Name: "tag",
Expand All @@ -350,8 +351,10 @@ func createPipelineSpec(tool string, commitTime int64, jbsConfig *v1alpha12.JBSC
}

tagDepends := artifactbuild.BuildTaskName
tagDigest := "$(tasks." + artifactbuild.BuildTaskName + ".results." + PipelineResultImageDigest + ")"
if hermeticBuildRequired {
tagDepends = artifactbuild.HermeticBuildTaskName
tagDigest = "$(tasks." + artifactbuild.HermeticBuildTaskName + ".results." + PipelineResultImageDigest + ")"
}
hermeticBuildPipelineTask := pipelinev1beta1.PipelineTask{
Name: artifactbuild.HermeticBuildTaskName,
Expand All @@ -373,7 +376,8 @@ func createPipelineSpec(tool string, commitTime int64, jbsConfig *v1alpha12.JBSC
TaskSpec: &pipelinev1beta1.EmbeddedTask{
TaskSpec: tagTask,
},
Params: []pipelinev1beta1.Param{}, Workspaces: []pipelinev1beta1.WorkspacePipelineTaskBinding{
Params: []pipelinev1beta1.Param{{Name: DeployedImageDigest, Value: pipelinev1beta1.ParamValue{Type: pipelinev1beta1.ParamTypeString, StringVal: tagDigest}}},
Workspaces: []pipelinev1beta1.WorkspacePipelineTaskBinding{
{Name: WorkspaceBuildSettings, Workspace: WorkspaceBuildSettings},
{Name: WorkspaceSource, Workspace: WorkspaceSource},
{Name: WorkspaceTls, Workspace: WorkspaceTls},
Expand Down Expand Up @@ -586,7 +590,7 @@ func gitArgs(db *v1alpha12.DependencyBuild, recipe *v1alpha12.BuildRecipe) strin
return gitArgs
}

func imageRegistryCommands(imageId string, recipe *v1alpha12.BuildRecipe, db *v1alpha12.DependencyBuild, jbsConfig *v1alpha12.JBSConfig, hermeticBuild bool) ([]string, []string, []string, []string, []string) {
func imageRegistryCommands(imageId string, recipe *v1alpha12.BuildRecipe, db *v1alpha12.DependencyBuild, jbsConfig *v1alpha12.JBSConfig, hermeticBuild bool, buildId string) ([]string, []string, []string, []string, []string) {

preBuildImageTag := imageId + "-pre-build-image"
preBuildImageArgs := []string{
Expand All @@ -607,23 +611,17 @@ func imageRegistryCommands(imageId string, recipe *v1alpha12.BuildRecipe, db *v1
"--build-info-path=$(workspaces.source.path)/build-info",
"--source-path=$(workspaces.source.path)/source",
"--task-run-name=$(context.taskRun.name)",
"--build-id=" + buildId,
"--scm-uri=" + db.Spec.ScmInfo.SCMURL,
"--scm-commit=" + db.Spec.ScmInfo.CommitHash,
}
hermeticDeployArgs := append([]string{}, deployArgs...)
hermeticDeployArgs = append(hermeticDeployArgs, "--image-id="+hermeticImageId)
deployArgs = append(deployArgs, "--image-id="+imageId)

var imageIdToTag string
if hermeticBuild {
imageIdToTag = hermeticImageId
} else {
imageIdToTag = imageId
}

tagArgs := []string{
"tag-container",
"--image-id=" + imageIdToTag, //TODO: hash
"--image-digest=$(params." + DeployedImageDigest + ")",
}
imageRegistry := jbsConfig.ImageRegistry()
registryArgs := make([]string, 0)
Expand Down
Loading

0 comments on commit 997e6f0

Please sign in to comment.