apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: publish-operator-release
spec:
  params:
    - name: package
      description: package to release (e.g. github.com/<org>/<project>)
      default: github.com/tektoncd/operator
    - name: images
      description: List of cmd/<kubeDistro>/* paths to be published as images
      default: "operator webhook proxy-webhook"
    - name: versionTag
      description: The vX.Y.Z version that the artifacts should be tagged with (including `v`)
    - name: imageRegistry
      description: The target image registry
      default: gcr.io
    - name: imageRegistryPath
      description: The path (project) in the image registry
    - name: imageRegistryRegions
      description: The target image registry regions
      default: "us eu asia"
    - name: releaseAsLatest
      description: Whether to tag and publish this release as Pipelines' latest
      default: "true"
    - name: platforms
      description: Platforms to publish for the images (e.g. linux/amd64,linux/arm64)
      default: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le
    - name: serviceAccountPath
      description: The name of the service account path within the release-secret workspace
    - name: kubeDistro
      description: The kubernetes distro targeted in a build. (kubernetes, openshift ...)
      default: kubernetes
  workspaces:
    - name: source
      description: >-
        The workspace where the repo has been cloned. This should ideally
        be /go/src/$(params.package) however that is not possible today,
        see https://github.com/tektoncd/pipeline/issues/3786. To use this
        task on a fork of pipeline change the mountPath below
      mountPath: /go/src/github.com/tektoncd/operator
    - name: release-secret
      description: The secret that contains a service account authorized to push to the imageRegistry and to the output bucket
    - name: output
      description: The release YAML will be written to this workspace
  stepTemplate:
    env:
      - name: "PROJECT_ROOT"
        value: "$(workspaces.source.path)"
      - name: CONTAINER_REGISTY_CREDENTIALS
        value: "$(workspaces.release-secret.path)/$(params.serviceAccountPath)"
      - name: CONTAINER_REGISTRY
        value: "$(params.imageRegistry)/$(params.imageRegistryPath)"
      - name: REGIONS
        value: "$(params.imageRegistryRegions)"
      - name: OUTPUT_RELEASE_DIR
        value: "$(workspaces.output.path)/$(params.versionTag)"
      - name: KUBE_DISTRO
        value: "$(params.kubeDistro)"
  steps:

  - name: container-registy-auth
    image: gcr.io/go-containerregistry/crane:debug
    script: |
      #!/busybox/sh
      set -ex

      # Login to the container registry
      DOCKER_CONFIG=$(cat ${CONTAINER_REGISTY_CREDENTIALS} | \
        crane auth login -u _json_key --password-stdin $(params.imageRegistry) 2>&1 | \
        sed 's,^.*logged in via \(.*\)$,\1,g')

      # Auth with account credentials for all regions.
      for region in ${REGIONS}
      do
        HOSTNAME=${region}.$(params.imageRegistry)
        cat ${CONTAINER_REGISTY_CREDENTIALS} | crane auth login -u _json_key --password-stdin ${HOSTNAME}
      done
      cp ${DOCKER_CONFIG} /workspace/docker-config.json

  - name: run-kustomize-ko
    image: gcr.io/tekton-releases/dogfooding/ko-gcloud:latest
    env:
    - name: KO_DOCKER_REPO
      value: $(params.imageRegistry)/$(params.imageRegistryPath)
    - name: GO111MODULE
      value: "on"
    - name: GOFLAGS
      value: "-mod=vendor"
    script: |
      #!/usr/bin/env sh
      set -ex

      # Setup docker-auth
      DOCKER_CONFIG=~/.docker
      mkdir -p ${DOCKER_CONFIG}
      cp /workspace/docker-config.json ${DOCKER_CONFIG}/config.json

      # Change to directory with our .ko.yaml
      cd ${PROJECT_ROOT}

      # For each cmd/<kubeDistro>/* directory, include a full gzipped tar of all source in
      # vendor/. This is overkill. Some deps' licenses require the source to be
      # included in the container image when they're used as a dependency.
      # Rather than trying to determine which deps have this requirement (and
      # probably get it wrong), we'll just targz up the whole vendor tree and
      # include it. As of 9/20/2019, this amounts to about 11MB of additional
      # data in each image.
      TMPDIR=$(mktemp -d)
      tar cfz ${TMPDIR}/source.tar.gz vendor/
      for d in cmd/${KUBE_DISTRO}/*; do
        if [ -d ${d}/kodata/ ]; then
          ln -s ${TMPDIR}/source.tar.gz ${d}/kodata/
        fi
      done

      # Rewrite "devel" to params.versionTag
      sed -i -e 's/\(operator.tekton.dev\/release\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\(app.kubernetes.io\/version\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\(version\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\("-version"\), "devel"/\1, "$(params.versionTag)"/g' ${PROJECT_ROOT}/config/base/*.yaml
      sed -i -e 's/\(operator.tekton.dev\/release\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\(app.kubernetes.io\/version\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\(version\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\("-version"\), "devel"/\1, "$(params.versionTag)"/g' ${PROJECT_ROOT}/config/${KUBE_DISTRO}/base/*.yaml
      sed -i -e 's/\(operator.tekton.dev\/release\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\(app.kubernetes.io\/version\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\(version\): "devel"/\1: "$(params.versionTag)"/g' -e 's/\("-version"\), "devel"/\1, "$(params.versionTag)"/g' ${PROJECT_ROOT}/config/${KUBE_DISTRO}/overlays/default/*.yaml

      # Publish images and create release.yaml
      mkdir -p $OUTPUT_RELEASE_DIR

      kustomize build ${PROJECT_ROOT}/config/${KUBE_DISTRO}/overlays/default | ko resolve --platform=$(params.platforms) --preserve-import-paths -t $(params.versionTag) -f - > $OUTPUT_RELEASE_DIR/release.yaml
      # Publish images and create release.notags.yaml
      # This is useful if your container runtime doesn't support the `image-reference:tag@digest` notation
      # This is currently the case for `cri-o` (and most likely others)
      kustomize build ${PROJECT_ROOT}/config/${KUBE_DISTRO}/overlays/default | ko resolve --platform=$(params.platforms) --preserve-import-paths -f - > $OUTPUT_RELEASE_DIR/release.notags.yaml

  - name: koparse
    image: gcr.io/tekton-releases/dogfooding/koparse:latest
    script: |
      set -ex

      IMAGES_PATH=${CONTAINER_REGISTRY}/$(params.package)

      for cmd in $(params.images)
      do
        IMAGES="${IMAGES} ${IMAGES_PATH}/cmd/${KUBE_DISTRO}/${cmd}:$(params.versionTag)"
      done

      # Parse the built images from the release.yaml generated by ko
      koparse \
        --path $OUTPUT_RELEASE_DIR/release.yaml \
        --base ${IMAGES_PATH} --images ${IMAGES} > /workspace/built_images

  - name: tag-images
    image: gcr.io/go-containerregistry/crane:debug
    script: |
      #!/busybox/sh
      set -ex

      # Setup docker-auth
      DOCKER_CONFIG=~/.docker
      mkdir -p ${DOCKER_CONFIG}
      cp /workspace/docker-config.json ${DOCKER_CONFIG}/config.json

      REGIONS="us eu asia"

      # Tag the images and put them in all the regions
      for IMAGE in $(cat /workspace/built_images)
      do
        IMAGE_WITHOUT_SHA=${IMAGE%%@*}
        IMAGE_WITHOUT_SHA_AND_TAG=${IMAGE_WITHOUT_SHA%%:*}
        IMAGE_WITH_SHA=${IMAGE_WITHOUT_SHA_AND_TAG}@${IMAGE##*@}

        if [[ "$(params.releaseAsLatest)" == "true" ]]
        then
          crane cp ${IMAGE_WITH_SHA} ${IMAGE_WITHOUT_SHA_AND_TAG}:latest
        fi

        for REGION in ${REGIONS}
        do
          if [[ "$(params.releaseAsLatest)" == "true" ]]
          then
            for TAG in "latest" $(params.versionTag)
            do
              crane cp ${IMAGE_WITH_SHA} ${REGION}.${IMAGE_WITHOUT_SHA_AND_TAG}:$TAG
            done
          else
            TAG="$(params.versionTag)"
            crane cp ${IMAGE_WITH_SHA} ${REGION}.${IMAGE_WITHOUT_SHA_AND_TAG}:$TAG
          fi
        done
      done
