mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-10 03:27:54 +00:00
fix: allow republish after review withdrawal
This commit is contained in:
parent
b01bedf392
commit
96dcf08b0e
2 changed files with 84 additions and 2 deletions
|
|
@ -227,8 +227,13 @@ public class SkillPublishService {
|
|||
}
|
||||
|
||||
// 7. Check version doesn't already exist
|
||||
if (skillVersionRepository.findBySkillIdAndVersion(skill.getId(), metadata.version()).isPresent()) {
|
||||
throw new DomainBadRequestException("error.skill.version.exists", metadata.version());
|
||||
java.util.Optional<SkillVersion> existingVersion = skillVersionRepository.findBySkillIdAndVersion(skill.getId(), metadata.version());
|
||||
if (existingVersion.isPresent()) {
|
||||
SkillVersion matchedVersion = existingVersion.get();
|
||||
if (matchedVersion.getStatus() == SkillVersionStatus.PUBLISHED) {
|
||||
throw new DomainBadRequestException("error.skill.version.exists", metadata.version());
|
||||
}
|
||||
deleteReplaceableVersionArtifacts(skill, matchedVersion);
|
||||
}
|
||||
|
||||
// 8. Create SkillVersion
|
||||
|
|
@ -333,6 +338,27 @@ public class SkillPublishService {
|
|||
return new PublishResult(skill.getId(), skill.getSlug(), version);
|
||||
}
|
||||
|
||||
private void deleteReplaceableVersionArtifacts(Skill skill, SkillVersion version) {
|
||||
if (version.getStatus() == SkillVersionStatus.PUBLISHED) {
|
||||
throw new DomainBadRequestException("error.skill.version.exists", version.getVersion());
|
||||
}
|
||||
|
||||
reviewTaskRepository.findBySkillVersionIdAndStatus(version.getId(), ReviewTaskStatus.PENDING)
|
||||
.ifPresent(reviewTaskRepository::delete);
|
||||
|
||||
List<SkillFile> files = skillFileRepository.findByVersionId(version.getId());
|
||||
if (!files.isEmpty()) {
|
||||
objectStorageService.deleteObjects(files.stream().map(SkillFile::getStorageKey).toList());
|
||||
}
|
||||
objectStorageService.deleteObject(String.format("packages/%d/%d/bundle.zip", skill.getId(), version.getId()));
|
||||
skillFileRepository.deleteByVersionId(version.getId());
|
||||
skillVersionRepository.delete(version);
|
||||
|
||||
if (version.getId().equals(skill.getLatestVersionId())) {
|
||||
skill.setLatestVersionId(null);
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveNamespaceSlug(Long namespaceId) {
|
||||
return namespaceRepository.findById(namespaceId)
|
||||
.orElseThrow(() -> new DomainBadRequestException("error.namespace.notFound", namespaceId))
|
||||
|
|
|
|||
|
|
@ -142,6 +142,62 @@ class SkillPublishServiceTest {
|
|||
verify(eventPublisher, never()).publishEvent(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPublishFromEntries_ShouldReplaceDraftVersionWithSameVersion() throws Exception {
|
||||
String namespaceSlug = "test-ns";
|
||||
String publisherId = "user-100";
|
||||
String skillMdContent = "---\nname: test-skill\ndescription: Test\nversion: 1.0.0\n---\nBody";
|
||||
|
||||
PackageEntry skillMd = new PackageEntry("SKILL.md", skillMdContent.getBytes(), skillMdContent.length(), "text/markdown");
|
||||
List<PackageEntry> entries = List.of(skillMd);
|
||||
|
||||
Namespace namespace = new Namespace(namespaceSlug, "Test NS", "user-1");
|
||||
setId(namespace, 1L);
|
||||
NamespaceMember member = mock(NamespaceMember.class);
|
||||
SkillMetadata metadata = new SkillMetadata("test-skill", "Test", "1.0.0", "Body", Map.of());
|
||||
|
||||
Skill skill = new Skill(1L, "test-skill", publisherId, SkillVisibility.PUBLIC);
|
||||
setId(skill, 1L);
|
||||
SkillVersion draftVersion = new SkillVersion(1L, "1.0.0", publisherId);
|
||||
draftVersion.setStatus(SkillVersionStatus.DRAFT);
|
||||
setId(draftVersion, 8L);
|
||||
SkillFile oldFile = new SkillFile(8L, "SKILL.md", (long) skillMdContent.length(), "text/markdown", "abc", "skills/1/8/SKILL.md");
|
||||
|
||||
when(namespaceRepository.findBySlug(namespaceSlug)).thenReturn(Optional.of(namespace));
|
||||
when(namespaceMemberRepository.findByNamespaceIdAndUserId(any(), eq(publisherId))).thenReturn(Optional.of(member));
|
||||
when(skillPackageValidator.validate(entries)).thenReturn(ValidationResult.pass());
|
||||
when(skillMetadataParser.parse(skillMdContent)).thenReturn(metadata);
|
||||
when(prePublishValidator.validate(any())).thenReturn(ValidationResult.pass());
|
||||
when(skillRepository.findByNamespaceIdAndSlug(any(), eq("test-skill"))).thenReturn(List.of(skill));
|
||||
when(skillRepository.findByNamespaceIdAndSlugAndOwnerId(any(), eq("test-skill"), eq(publisherId))).thenReturn(Optional.of(skill));
|
||||
when(skillVersionRepository.findBySkillIdAndStatus(1L, SkillVersionStatus.PENDING_REVIEW)).thenReturn(List.of());
|
||||
when(skillVersionRepository.findBySkillIdAndVersion(1L, "1.0.0")).thenReturn(Optional.of(draftVersion));
|
||||
when(skillFileRepository.findByVersionId(8L)).thenReturn(List.of(oldFile));
|
||||
when(skillVersionRepository.save(any(SkillVersion.class))).thenAnswer(invocation -> {
|
||||
SkillVersion saved = invocation.getArgument(0);
|
||||
if (saved.getId() == null) {
|
||||
setId(saved, 10L);
|
||||
}
|
||||
return saved;
|
||||
});
|
||||
when(skillRepository.save(any())).thenReturn(skill);
|
||||
|
||||
SkillPublishService.PublishResult result = service.publishFromEntries(
|
||||
namespaceSlug,
|
||||
entries,
|
||||
publisherId,
|
||||
SkillVisibility.PUBLIC,
|
||||
Set.of()
|
||||
);
|
||||
|
||||
assertEquals("1.0.0", result.version().getVersion());
|
||||
assertEquals(SkillVersionStatus.PENDING_REVIEW, result.version().getStatus());
|
||||
verify(skillFileRepository).deleteByVersionId(8L);
|
||||
verify(skillVersionRepository).delete(draftVersion);
|
||||
verify(objectStorageService).deleteObjects(List.of("skills/1/8/SKILL.md"));
|
||||
verify(objectStorageService).deleteObject("packages/1/8/bundle.zip");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPublishFromEntries_ShouldSlugifyNameBeforeLookupAndResponse() throws Exception {
|
||||
String namespaceSlug = "test-ns";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue