Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V0.10.x fix translate semver tags #700

Merged
merged 4 commits into from
Jan 13, 2025
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- #474: When loading a .tgz/.tar.gz package, automatically locate the top-most module.xml in case there is nested directory structure (e.g., GitHub releases)
- #635: When calling the "package" command, the directory is now normalized to include trailing slash (or backslash).
- #696: Fix a bug that caused error status to be ignored when publishing a module.
- #700: Fix a bug due to incompatible conventions between SemVer and OCI tags

### Security
-
Expand Down
20 changes: 11 additions & 9 deletions src/cls/IPM/Repo/Oras/PackageService.cls
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Method IsAvailable() As %Boolean

Method GetModule(pModuleReference As %IPM.Storage.ModuleInfo, Output AsArchive As %Boolean = 0) As %Stream.Object
{
Set name = pModuleReference.Name _ ":" _ pModuleReference.VersionString
Set name = pModuleReference.Name _ ":" _ $$$Semver2Tag(pModuleReference.VersionString)
Set status = ..Pull(..Location, name, ..Namespace, ..Username, ..Password, ..Token, ..TokenAuthMethod, .stream)
$$$ThrowOnError(status)
#; module is pulled as a .tgz file
Expand All @@ -42,13 +42,13 @@ Method GetModule(pModuleReference As %IPM.Storage.ModuleInfo, Output AsArchive A

Method GetModuleManifest(pModuleReference As %IPM.Storage.ModuleInfo) As %Stream.Object
{
Set name = pModuleReference.Name _ ":" _ pModuleReference.VersionString
Set name = pModuleReference.Name _ ":" _ $$$Semver2Tag(pModuleReference.VersionString)
Return ..GetModuleXMLPy(..Location, name, ..Namespace, ..Username, ..Password, ..Token, ..TokenAuthMethod)
}

Method HasModule(pModuleReference As %IPM.Storage.ModuleInfo) As %Boolean
{
Set name = pModuleReference.Name _ ":" _ pModuleReference.VersionString
Set name = pModuleReference.Name _ ":" _ $$$Semver2Tag(pModuleReference.VersionString)

#; Get ORAS client
Set client = ..GetClient(..Location, ..Username, ..Password, ..Token, ..TokenAuthMethod)
Expand Down Expand Up @@ -238,7 +238,7 @@ ClassMethod PullOras(registry As %String, package As %String, namespace As %Stri
{
Set pkgTag = ..GetPackageVersionPy(registry, package, namespace, username, password, token, tokenAuthMethod, 1)
Set pkg = $PIECE(pkgTag, ",", 1)
Set tag = $PIECE(pkgTag, ",", 2)
Set tag = $$$Semver2Tag($PIECE(pkgTag, ",", 2))

Set target = ..GetAPITarget(registry, pkg, namespace) _ ":" _ tag
Set client = ..GetClient(registry, username, password, token, tokenAuthMethod)
Expand Down Expand Up @@ -295,9 +295,9 @@ ClassMethod GetPackageMetadataPy(registry As %String, package As %String, namesp
/// Given a package name, either parses out the tag or determines the latest tag
/// Params:
/// package : is either in the form <package>:<tag> or <package>
/// in the latter case, returns latest tag
/// asString : 0 => returns as python tuple of (package, tag)
/// 1 => returns as string of "<package>,<tag>"
/// in the latter case, returns semver corresponding to the latest tag
/// asString : 0 => returns as python tuple of (package, semver)
/// 1 => returns as string of "<package>,<semver>"
ClassMethod GetPackageVersionPy(registry As %String, package As %String, namespace As %String, username As %String, password As %String, token As %String, tokenAuthMethod As %String, asString As %Boolean = 0) [ Language = python ]
{
import iris
Expand All @@ -307,10 +307,12 @@ ClassMethod GetPackageVersionPy(registry As %String, package As %String, namespa
else:
pkg = package
tag = iris.cls("%IPM.Repo.Oras.PackageService").GetLatestTagPy(registry, pkg, namespace, username, password, token, tokenAuthMethod, asString )

semver = tag.replace("_", "+")
if asString:
return pkg + "," + tag
return pkg + "," + semver
else:
return (pkg, tag)
return (pkg, semver)
}

/// Lists all of the modules and their latest versions in the package
Expand Down
24 changes: 13 additions & 11 deletions src/cls/IPM/Repo/Oras/PublishService.cls
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Include %IPM.Common

Class %IPM.Repo.Oras.PublishService Extends (%IPM.Repo.Oras.PackageService, %IPM.Repo.IPublishService)
{

Expand All @@ -6,7 +8,7 @@ Method PublishModule(pModule As %IPM.Repo.Remote.ModuleInfo) As %Status
Set status = $$$OK
Try {
Set repo = pModule.Name
Set tag = pModule.VersionString
Set tag = $$$Semver2Tag(pModule.VersionString)

#; Use a temp directory
Set tDir = $$$FileTempDir
Expand Down Expand Up @@ -85,7 +87,7 @@ ClassMethod Push(registry As %String, package As %String, namespace As %String,
{
#; Remove the tag from the package name if it exists and add it to tags
Set repo = $piece(package, ":", 1)
Set tag = $piece(package, ":", 2)
Set tag = $$$Semver2Tag($piece(package, ":", 2))
If tag '= "" { Set tags = tags _ "," _ tag }
If tags = "" {
$$$ThrowStatus($$$ERROR($$$GeneralError,"Must specify version."))
Expand All @@ -108,31 +110,31 @@ ClassMethod PushPy(registry As %String, package As %String, namespace As %String
import iris
import os, sys
import json
import re

# Get all files in the directory and fully specify path
files = os.listdir(directoryPath)
result = map(lambda x: directoryPath + x, files)
file_paths = list(result)

file_paths = [os.path.join(directoryPath, f) for f in os.listdir(directoryPath)]
client = iris.cls("%IPM.Repo.Oras.PackageService").GetClient(registry, username, password, token, tokenAuthMethod)
regex = re.compile(r"^[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}$")

# Push once for each tag
for tag in tags.split(","):
if tag == "":
continue
if not regex.search(tag):
raise ValueError(f"Invalid OCI tag: {tag}")

# Annotations are manifest.xml and other metadata
manifest_annotations = json.loads(metadata)

# TODO write a context manager for stdout/stderr redirection
# Suppress console output
sys.stdout = open(os.devnull, "w")

target = iris.cls("%IPM.Repo.Oras.PackageService").GetAPITarget(registry, package, namespace) + ":" + tag

try:
target = iris.cls("%IPM.Repo.Oras.PackageService").GetAPITarget(registry, package, namespace) + ":" + tag
res = client.push(files=file_paths, target=target, disable_path_validation=True, manifest_annotations=manifest_annotations)
except Exception as e:
print("Error: ", repr(e))
print("Error: ", repr(e), file=sys.stderr)
sys.stdout = sys.__stdout__
raise e

# Reenable console output
Expand Down
6 changes: 5 additions & 1 deletion src/inc/IPM/Common.inc
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,8 @@ ROUTINE %IPM.Common [Type=INC]
#def1arg ENDTAG ##Expression($$$ENDTAGQ)

#; Variable to mark deprecation warning has been shown in the current process
#define DeprecationWarned %IPMModuleDeprecatedResource
#define DeprecationWarned %IPMModuleDeprecatedResource

#; Convert module version from/to OCI tag
#def1arg Semver2Tag(%semver) $Replace(%semver,"+","_")
isc-shuliu marked this conversation as resolved.
Show resolved Hide resolved
#def1arg Tag2Semver(%tag) $Replace(%tag,"_","+")
35 changes: 35 additions & 0 deletions tests/integration_tests/Test/PM/Integration/OrasTag.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Class Test.PM.Integration.OrasTag Extends Test.PM.Integration.Base
{

Parameter TargetModuleName As STRING = "oras-tag";

Method TestOrasTagConversion()
{
Set tModuleDir = ..GetModuleDir(..#TargetModuleName)

Set tSC = ##class(%IPM.Main).Shell("load -verbose " _ tModuleDir)
Do $$$AssertStatusOK(tSC,"Loaded module successfully")

Set tSC = ##class(%IPM.Main).Shell("repo -delete-all")
Do $$$AssertStatusOK(tSC,"Deleted repos successfully")

Set tSC = ##class(%IPM.Main).Shell("repo -o -name oras -url http://oras:5000 -publish 1")
Do $$$AssertStatusOK(tSC,"Set up oras module successfully")

Set tSC = ##class(%IPM.Main).Shell("publish oras-tag -r oras -verbose")
Do $$$AssertStatusOK(tSC,"Published module successfully")

Set tSC = ##class(%IPM.Main).Shell("uninstall oras-tag")
Do $$$AssertStatusOK(tSC,"Uninstalled module successfully")

Set tSC = ##class(%IPM.Main).Shell("install oras-tag")
Do $$$AssertStatusOK(tSC,"Installed module from ORAS registry successfully")

Set tSC = ##class(%IPM.Main).Shell("repo -delete-all")
Do $$$AssertStatusOK(tSC,"Deleted repos successfully")

Set tSC = ##class(%IPM.Main).Shell("repo -reset-defaults")
Do $$$AssertStatusOK(tSC,"Reset repos to default successfully")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="oras-tag.ZPM">
<Module>
<Name>oras-tag</Name>
<Version>0.0.1-beta.1+build</Version>
<Packaging>module</Packaging>
<SourcesRoot>src</SourcesRoot>
<Resource Name="OrasTag.Main.CLS"/>
</Module>
</Document>
</Export>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Class OrasTag.Main
{

ClassMethod Main()
{
Write "This is OrasTag.main"
}

}
Loading