Skip to content

Commit fb8dc52

Browse files
authored
fix(import): Fix an issue where migrating from v2 to v3 failed to create the "latest" branch (#5674)
* Fix an issue where migrating from v2 to v3 failed to create the "latest" branch * spotless:apply * Sort versions when importing from a v2 zip * Fix the version sort in EntityReader
1 parent c434b05 commit fb8dc52

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

app/src/main/java/io/apicurio/registry/storage/importing/v2/SqlDataUpgrader.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import io.apicurio.registry.content.ContentHandle;
44
import io.apicurio.registry.content.TypedContent;
5+
import io.apicurio.registry.model.BranchId;
6+
import io.apicurio.registry.model.GA;
7+
import io.apicurio.registry.model.VersionId;
58
import io.apicurio.registry.storage.RegistryStorage;
69
import io.apicurio.registry.storage.dto.ArtifactReferenceDto;
710
import io.apicurio.registry.storage.dto.ArtifactVersionMetaDataDto;
@@ -23,6 +26,7 @@
2326
import io.apicurio.registry.utils.impexp.v2.GlobalRuleEntity;
2427
import io.apicurio.registry.utils.impexp.v2.GroupEntity;
2528
import io.apicurio.registry.utils.impexp.v3.ArtifactEntity;
29+
import io.apicurio.registry.utils.impexp.v3.BranchEntity;
2630
import org.apache.commons.codec.digest.DigestUtils;
2731
import org.slf4j.Logger;
2832

@@ -124,10 +128,17 @@ public void importArtifactVersion(ArtifactVersionEntity entity) {
124128
.modifiedBy(entity.createdBy).modifiedOn(entity.createdOn).name(entity.name)
125129
.owner(entity.createdBy).build();
126130
storage.importArtifact(artifactEntity);
131+
132+
// Also create the "latest" branch.
133+
BranchEntity branchEntity = BranchEntity.builder().groupId(entity.groupId)
134+
.artifactId(entity.artifactId).branchId("latest").createdOn(entity.createdOn)
135+
.owner(entity.createdBy).modifiedOn(entity.createdOn).modifiedBy(entity.createdBy)
136+
.build();
137+
storage.importBranch(branchEntity);
127138
}
128139

140+
// If this version is the latest, update the artifact metadata with its metadata
129141
if (entity.isLatest) {
130-
// If this version is the latest, update the artifact metadata with its metadata
131142
EditableArtifactMetaDataDto editableArtifactMetaDataDto = EditableArtifactMetaDataDto
132143
.builder().name(newEntity.name).owner(newEntity.owner)
133144
.description(newEntity.description).labels(newEntity.labels).build();
@@ -139,6 +150,14 @@ public void importArtifactVersion(ArtifactVersionEntity entity) {
139150
storage.importArtifactVersion(newEntity);
140151
log.debug("Artifact version imported successfully: {}", entity);
141152
globalIdMapping.put(oldGlobalId, entity.globalId);
153+
154+
// Append this version to the "latest" branch
155+
String entityVersion = entity.version;
156+
if (entityVersion == null) {
157+
entityVersion = String.valueOf(entity.versionId);
158+
}
159+
storage.appendVersionToBranch(new GA(entity.groupId, entity.artifactId), new BranchId("latest"),
160+
new VersionId(entityVersion));
142161
} catch (VersionAlreadyExistsException ex) {
143162
if (ex.getGlobalId() != null) {
144163
log.warn("Duplicate globalId {} detected, skipping import of artifact version: {}",

app/src/test/java/io/apicurio/registry/DataUpgradeTest.java

+46
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
import io.apicurio.registry.model.GroupId;
44
import io.apicurio.registry.rest.client.models.ArtifactReference;
5+
import io.apicurio.registry.rest.client.models.ArtifactSearchResults;
6+
import io.apicurio.registry.rest.client.models.BranchMetaData;
57
import io.apicurio.registry.rest.client.models.HandleReferencesType;
8+
import io.apicurio.registry.rest.client.models.ProblemDetails;
9+
import io.apicurio.registry.rest.client.models.VersionMetaData;
610
import io.apicurio.registry.storage.RegistryStorage;
711
import io.apicurio.registry.types.Current;
812
import io.apicurio.registry.utils.IoUtil;
@@ -152,4 +156,46 @@ public void testCheckJsonWithReferences() throws Exception {
152156
* HandleReferencesType.DEREFERENCE; }));
153157
*/
154158
}
159+
160+
@Test
161+
public void testLatestBranch() {
162+
try {
163+
ArtifactSearchResults results = clientV3.search().artifacts().get();
164+
results.getArtifacts().forEach(artifact -> {
165+
String groupId = "default";
166+
if (artifact.getGroupId() != null) {
167+
groupId = artifact.getGroupId();
168+
}
169+
BranchMetaData branchMetaData = clientV3.groups().byGroupId(groupId).artifacts()
170+
.byArtifactId(artifact.getArtifactId()).branches().byBranchId("latest").get();
171+
Assertions.assertNotNull(branchMetaData);
172+
Assertions.assertEquals(artifact.getGroupId(), branchMetaData.getGroupId());
173+
Assertions.assertEquals(artifact.getArtifactId(), branchMetaData.getArtifactId());
174+
Assertions.assertEquals("latest", branchMetaData.getBranchId());
175+
176+
VersionMetaData versionMetaData = clientV3.groups().byGroupId(groupId).artifacts()
177+
.byArtifactId(artifact.getArtifactId()).versions()
178+
.byVersionExpression("branch=latest").get();
179+
Assertions.assertNotNull(versionMetaData);
180+
Assertions.assertEquals(artifact.getGroupId(), versionMetaData.getGroupId());
181+
Assertions.assertEquals(artifact.getArtifactId(), versionMetaData.getArtifactId());
182+
});
183+
184+
// Make sure the latest version of "MixAvroExample/Farewell" is version "2"
185+
VersionMetaData versionMetaData = clientV3.groups().byGroupId("MixAvroExample").artifacts()
186+
.byArtifactId("Farewell").versions().byVersionExpression("branch=latest").get();
187+
Assertions.assertNotNull(versionMetaData);
188+
Assertions.assertEquals("2", versionMetaData.getVersion());
189+
190+
// Make sure the latest version of "default/city" is version "2"
191+
versionMetaData = clientV3.groups().byGroupId("default").artifacts().byArtifactId("city")
192+
.versions().byVersionExpression("branch=latest").get();
193+
Assertions.assertNotNull(versionMetaData);
194+
Assertions.assertEquals("2", versionMetaData.getVersion());
195+
} catch (ProblemDetails e) {
196+
System.err.println("ERROR: " + e.getDetail());
197+
throw e;
198+
}
199+
}
200+
155201
}

utils/importexport/src/main/java/io/apicurio/registry/utils/impexp/EntityReader.java

+29
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,25 @@ private void createEntityIndex() {
159159
}
160160
}
161161

162+
if (manifest == null) {
163+
throw new RuntimeException("No manifest found");
164+
}
165+
try {
166+
readManifest(manifest);
167+
} catch (IOException e) {
168+
throw new RuntimeException("Invalid manifest: ", e);
169+
}
170+
171+
// Make sure we sort the versions when upgrading from v2 to v3 - this is
172+
// so that the "latest" branch contains the versions in the correct order.
173+
if (majorVersion == 2) {
174+
versions.sort((v1, v2) -> {
175+
long v1GlobalId = getArtifactVersionOrder(v1);
176+
long v2GlobalId = getArtifactVersionOrder(v2);
177+
return (int) (v1GlobalId - v2GlobalId);
178+
});
179+
}
180+
162181
entities = new LinkedList<>();
163182
if (manifest != null) {
164183
entities.add(manifest);
@@ -269,4 +288,14 @@ private <T> T readEntry(EntityInfo entry, Class<T> theClass) throws IOException
269288
return entity;
270289
}
271290

291+
private long getArtifactVersionOrder(EntityInfo artifactVersionEntityInfo) {
292+
try {
293+
Entity entity = readArtifactVersion(artifactVersionEntityInfo);
294+
return ((io.apicurio.registry.utils.impexp.v2.ArtifactVersionEntity) entity).globalId;
295+
} catch (IOException e) {
296+
// Nothing we can do here. :(
297+
return 0;
298+
}
299+
}
300+
272301
}

0 commit comments

Comments
 (0)