[SEBA-497] Standalone docker-publish job

Change-Id: I5be59b002e58b0653d78d626640d74356a6ed1d1
diff --git a/jjb/defaults.yaml b/jjb/defaults.yaml
index 4863e0e..b1f4948 100644
--- a/jjb/defaults.yaml
+++ b/jjb/defaults.yaml
@@ -78,7 +78,7 @@
 
     # matching repos that should be version tagged by the version-tag job
     # (basically the same as imagebuilder projects + helm charts + tools
-    version-tag-projects-regexp: '^(xos.*|helm-charts|automation-tools|cord-tester|chameleon|rcord|mcord|ecord|acordion|addressmanager|epc-service|exampleservice|fabric|fabric-crossconnect|globalxos|hippie-oss|hss_db|hypercache|internetemulator|kubernetes-service|monitoring|olt-service|onos-service|openstack|progran|sdn-controller|simpleexampleservice|templateservice|vEE|vEG|vBBU|venb|vHSS|vMME|vnaas|vPGWC|vPGWU|vrouter|vsg|vsg-hw|vSGW|vSM|vspgwc|vspgwu|vtn-service|vtr|att-workflow-driver|tt-workflow-driver|ves-agent|voltha-bbsim|openolt|sadis-server|kafka-topic-exporter|pyvoltha|voltha-adtran-adapter|voltha-openolt-adapter|voltha-openonu-adapter|plyxproto|voltha-protos)$'
+    version-tag-projects-regexp: '^(xos.*|helm-charts|automation-tools|cord-tester|chameleon|rcord|mcord|ecord|acordion|addressmanager|epc-service|exampleservice|fabric|fabric-crossconnect|globalxos|hippie-oss|hss_db|hypercache|internetemulator|kubernetes-service|monitoring|olt-service|onos-service|openstack|progran|sdn-controller|simpleexampleservice|templateservice|vEE|vEG|vBBU|venb|vHSS|vMME|vnaas|vPGWC|vPGWU|vrouter|vsg|vsg-hw|vSGW|vSM|vspgwc|vspgwu|vtn-service|vtr|att-workflow-driver|tt-workflow-driver|ves-agent|voltha-bbsim|openolt|sadis-server|kafka-topic-exporter|pyvoltha|voltha-adtran-adapter|voltha-openolt-adapter|voltha-openonu-adapter|plyxproto|voltha-protos|alpine-grpc-base)$'
 
     # PyPI related publishing variables
     #
@@ -92,6 +92,11 @@
     # in the job once testing is completed
     pypi-index: 'testpypi'
 
+    # Name of the Docker repository (usually on DockerHub) that is the
+    # destination for images to be pushed to after building.
+    # Default is invalid - must be specified on every job.
+    docker-repo: 'default-and-invalid'
+
     # for matching files with file-include-regexp
     all-files-regexp: '.*'
     doc-files-regexp: '^docs/.*'
diff --git a/jjb/docker-publish.yaml b/jjb/docker-publish.yaml
new file mode 100644
index 0000000..9495c04
--- /dev/null
+++ b/jjb/docker-publish.yaml
@@ -0,0 +1,53 @@
+---
+# generic docker image building + dockerhub publishing tasks
+
+- job-template:
+    id: docker-publish
+    name: 'docker-publish_{project}'
+    description: |
+      Created by {id} job-template from ci-management/jjb/docker-publish.yaml
+
+    triggers:
+      - cord-infra-gerrit-trigger-merge:
+          gerrit-server-name: '{gerrit-server-name}'
+          project-regexp: '^{project}$'
+          branch-regexp: '{all-branches-regexp}'
+          file-include-regexp: '{all-files-regexp}'
+          dependency-jobs: '{dependency-jobs}'
+
+    properties:
+      - cord-infra-properties:
+          build-days-to-keep: '{build-days-to-keep}'
+          artifact-num-to-keep: '{artifact-num-to-keep}'
+
+    wrappers:
+      - lf-infra-wrappers:
+          build-timeout: '30'
+          jenkins-ssh-credential: '{jenkins-ssh-credential}'
+
+    parameters:
+      - string:
+          name: executorNode
+          default: 'ubuntu16.04-basebuild-1c-2g'
+          description: 'Name of the Jenkins node to run the job on'
+
+      - string:
+          name: gitUrl
+          default: '{gerrit-server-url}/{project}'
+          description: 'URL to the git repo'
+
+      - string:
+          name: dockerRepo
+          default: '{docker-repo}'
+          description: "Docker repository to push to ('opencord', 'xosproject', etc.)"
+
+      # AWS CPU arch names: `x86_64` `arm64` (which don't align to vendor names... *sigh*)
+      - string:
+          name: dockerArchList
+          default: 'x86_64'
+          description: "List of architectures to build containers on, pipe separated (nonfunctional currently)"
+
+    project-type: pipeline
+    concurrent: true
+
+    dsl: !include-raw-escape: pipeline/docker-publish.groovy
diff --git a/jjb/pipeline/docker-publish.groovy b/jjb/pipeline/docker-publish.groovy
new file mode 100644
index 0000000..89eef34
--- /dev/null
+++ b/jjb/pipeline/docker-publish.groovy
@@ -0,0 +1,97 @@
+/* docker-publish pipeline */
+pipeline {
+
+  /* no label, executor is determined by JJB */
+  agent {
+    label "${params.executorNode}"
+  }
+  stages {
+
+    stage('checkout') {
+      steps {
+        checkout([
+          $class: 'GitSCM',
+          userRemoteConfigs: [[
+            url: "${params.gitUrl}",
+            name: "${params.GERRIT_PATCHSET_REVISION}",
+          ]],
+          extensions: [
+            [$class: 'WipeWorkspace'],
+            [$class: 'RelativeTargetDirectory', relativeTargetDir: "${params.GERRIT_PROJECT}"],
+            [$class: 'CloneOption', depth: 0, noTags: false, reference: '', shallow: false],
+          ],
+        ])
+        script {
+          def git_tags={ shell "git tag -l --points-at HEAD" }
+        }
+      }
+    }
+
+    stage('build'){
+      steps {
+        sh """
+          #!/usr/bin/env bash
+          set -eu -o pipefail
+
+          # checked out in a subdir so the log can be in WORKSPACE
+          cd "$GERRIT_PROJECT"
+
+          export DOCKER_REPOSITORY="$dockerRepo/"
+
+          # Build w/branch
+          echo "Building image with branch"
+          make DOCKER_TAG="$GERRIT_BRANCH" docker-build 2>&1 | tee > "$WORKSPACE/docker-build.log"
+
+          # Build w/tags if they exist
+          if [ -n "$git_tags" ]
+          then
+            for tag in $git_tags
+            do
+              echo "Building image with tag (should reuse cached layers)"
+              make DOCKER_TAG="$tag" docker-build
+            done
+          fi
+        """
+      }
+    }
+
+    stage('push'){
+      steps {
+        script {
+          withDockerRegistry([credentialsId: 'docker-artifact-push-credentials']) {
+            sh """
+              #!/usr/bin/env bash
+              set -eu -o pipefail
+
+              # checked out in a subdir so the log can be in WORKSPACE
+              cd "$GERRIT_PROJECT"
+
+              export DOCKER_REPOSITORY="$dockerRepo/"
+
+              # Push w/branch
+              echo "Pushing image with branch"
+              make DOCKER_TAG="$GERRIT_BRANCH" docker-push 2>&1 | tee > "$WORKSPACE/docker-push.log"
+
+              # Push w/tags if they exist
+              if [ -n "$git_tags" ]
+              then
+                for tag in $git_tags
+                do
+                  echo "Pushing image with tag (should reuse cached layers)"
+                  make DOCKER_TAG="$tag" docker-push
+                done
+              fi
+            """
+          }
+        }
+      }
+    }
+  }
+
+  post {
+    always {
+      archiveArtifacts artifacts: 'docker-build.log', fingerprint: true
+      deleteDir()
+    }
+  }
+}
diff --git a/jjb/verify/alpine-grpc-base.yaml b/jjb/verify/alpine-grpc-base.yaml
index 0c823cc..7197480 100644
--- a/jjb/verify/alpine-grpc-base.yaml
+++ b/jjb/verify/alpine-grpc-base.yaml
@@ -8,6 +8,7 @@
     jobs:
       - 'verify-alpine-grpc-base-jobs':
           branch-regexp: '{all-branches-regexp}'
+      - 'publish-alpine-grpc-base-jobs'
 
 - job-group:
     name: 'verify-alpine-grpc-base-jobs'
@@ -15,3 +16,9 @@
       - 'verify-licensed'
       - 'tag-collision-reject':
           dependency-jobs: 'verify_alpine-grpc-base_licensed'
+
+- job-group:
+    name: 'publish-alpine-grpc-base-jobs'
+    jobs:
+      - 'docker-publish':
+          docker-repo: "xosproject"