Add support for uploading snapshot artifacts

Change-Id: Iedc62e422267016f315799addf394c0c062ada87
(cherry picked from commit 8a8b572dd23aac6095906576569121b748e30465)
diff --git a/tools/build/onos-build-and-upload-snapshot b/tools/build/onos-build-and-upload-snapshot
new file mode 100755
index 0000000..006f131
--- /dev/null
+++ b/tools/build/onos-build-and-upload-snapshot
@@ -0,0 +1,39 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Builds the snapshot artifacts and uploads them.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+# shellcheck disable=SC1090
+. "$ONOS_ROOT"/tools/build/envDefaults
+
+set -ex -o pipefail
+
+DRY_RUN=${1:-""}
+dryRun=0
+if [ "${DRY_RUN}" == "--dry-run" ]; then
+    dryRun=1
+fi
+
+[[ ! "$ONOS_POM_VERSION" =~ "SNAPSHOT" ]] && echo "Version is not a SNAPSHOT" && exit 1;
+
+cd "$ONOS_ROOT"
+
+# Build ONOS
+bazel build onos
+
+if [ $dryRun -eq 0 ]; then
+    publish_url="https://oss.sonatype.org/content/repositories/snapshots/"
+else
+    publish_url=""
+fi
+
+# Create artifact catalog
+onos-publish-catalog publishing-catalog-snapshot
+
+# publish artifacts with Maven
+if [ $dryRun -eq 0 ]; then
+    onos-maven-upload.py publishing-catalog-snapshot "${publish_url}"
+else
+    onos-maven-upload.py publishing-catalog-snapshot "${publish_url}" --dry_run
+fi
\ No newline at end of file
diff --git a/tools/build/onos-maven-upload.py b/tools/build/onos-maven-upload.py
new file mode 100755
index 0000000..61f1f15
--- /dev/null
+++ b/tools/build/onos-maven-upload.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+"""
+ Copyright 2021-present Open Networking Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+from subprocess import call
+import requests, os
+import argparse
+import sys
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='Upload artifacts with Maven.')
+    parser.add_argument('catalog_file_name', type=str, help="Catalog File Name")
+    parser.add_argument('destination_repo_url', type=str, nargs="?", default="",
+                        help="Nexus complete URL")
+    parser.add_argument('--local_settings', type=str, required=False, default=None,
+                        help="Use a local settings.xml instead of the default one")
+    parser.add_argument('--repo_id', type=str, required=False, default="snapshots",
+                        help="ID to map on the <id> under <server> section of settings.xml")
+    parser.add_argument('--group_id', type=str, required=False, default="org.onosproject",
+                        help="GroupId of the artifacts to be deployed")
+    parser.add_argument('--dry_run', action="store_true", required=False, default=False)
+    args = parser.parse_args()
+
+    input_list_file = args.catalog_file_name
+    destination_repo_url = args.destination_repo_url
+    local_settings_file = args.local_settings
+    repo_id = args.repo_id
+    group_id = args.group_id
+    dry_run = args.dry_run
+
+    with open(input_list_file, "r") as list_file:
+        lines = list_file.readlines()
+
+    artifacts_to_upload = {}
+    for line in lines:
+        s = line.split()
+        src = s[0]
+        dest = s[1]
+        artifactId = dest.split("/")[2]
+        info = artifacts_to_upload.get(artifactId, {})
+        version = dest.split("/")[3]
+        if info.get("version", None) is not None:
+            if info["version"] != version:
+                print("ERROR: Version mismatch: " + artifactId + ", Version: " +
+                      info["version"], ", New Version: " + version)
+                sys.exit(1)
+        else:
+            info['version'] = version
+        artifacts = info.get("artifacts", {})
+        src_and_extension = [src, os.path.splitext(src)[1].replace(".", '')]
+        if "-sources" in src:
+            artifacts["sources"] = src_and_extension
+        elif "-javadoc" in src:
+            artifacts["javadoc"] = src_and_extension
+        elif "-oar" in src:
+            artifacts["oar"] = src_and_extension
+        elif "-tests" in src:
+            artifacts["tests"] = src_and_extension
+        elif "-pom" in src:
+            artifacts["pom"] = src_and_extension
+        elif src.endswith(".jar"):
+            artifacts["jar"] = src_and_extension
+        # Exclude archives for now
+        # elif src.endswith(".tar.gz"):
+        #     artifacts["tar"] = [src, "targz"]
+        else:
+            print("WARNING: artifact " + dest + " not supported, skipping")
+        info["artifacts"] = artifacts
+        artifacts_to_upload[artifactId] = info
+
+    if dry_run:
+        print("------- Artifacts dictionary ---------")
+        print(artifacts_to_upload)
+        print("--------------------------------------")
+        print()
+
+    # Upload the artifacts to the remote Nexus repository
+    for artifact_id, info in artifacts_to_upload.items():
+        artifacts = info["artifacts"]
+        call_funct = ["mvn", "deploy:deploy-file",
+                      "-Durl=" + destination_repo_url,
+                      "-DrepositoryId=" + repo_id,
+                      "-DgroupId=" + group_id,
+                      "-DartifactId=" + artifact_id,
+                      "-Dversion=" + info["version"]]
+        if local_settings_file is not None:
+            call_funct.insert(1, "-s")
+            call_funct.insert(2, local_settings_file)
+
+        # If we have a pom, use it, otherwise do not let Maven generate one
+        if "pom" in artifacts.keys():
+            call_funct.append("-DpomFile=" + artifacts["pom"][0])
+            del artifacts["pom"]
+        else:
+            call_funct.append("-DgeneratePom=false")
+
+        # Find the main artifact, it can be a JAR or a OAR
+        if "jar" in artifacts.keys():
+            call_funct.append("-Dfile=" + artifacts["jar"][0])
+            del artifacts["jar"]
+        elif "oar" in artifacts.keys():
+            call_funct.append("-Dfile=" + artifacts["oar"][0])
+            del artifacts["oar"]
+        else:
+            print("WARNING: Skipping, no main artifact for artifact ID: " + artifact_id)
+            continue
+
+        if "javadoc" in artifacts.keys():
+            call_funct.append("-Djavadoc=" + artifacts["javadoc"][0])
+            del artifacts["javadoc"]
+        if "sources" in artifacts.keys():
+            call_funct.append("-Dsources=" + artifacts["sources"][0])
+            del artifacts["sources"]
+
+        # Build the list of the other files to upload together with the main artifact
+        other_files = []
+        other_files_types = []
+        other_files_classifier = []
+        for key, val in artifacts.items():
+            other_files.append(val[0])
+            other_files_types.append(val[1])
+            other_files_classifier.append(key)
+        if len(other_files) > 0:
+            call_funct.append("-Dfiles=" + ",".join(other_files))
+            call_funct.append("-Dtypes=" + ",".join(other_files_types))
+            call_funct.append("-Dclassifiers=" + ",".join(other_files_classifier))
+        if dry_run:
+            print(artifact_id + "\n" + " ".join(call_funct))
+            print()
+        else:
+            call(call_funct)