diff --git a/tasks/git-clone-checkout/task.yaml b/tasks/git-clone-checkout/task.yaml index dcdb03e..89f9e06 100644 --- a/tasks/git-clone-checkout/task.yaml +++ b/tasks/git-clone-checkout/task.yaml @@ -3,93 +3,114 @@ kind: Task metadata: name: git-clone-checkout spec: + description: | + This task clones a Git repository and checks out a specified branch if it exists. + Supports SSH, basic-auth, custom CA certs, sparse checkout, submodules, shallow clone, and proxy settings. + The commit SHA, committer date, and fetched URL are exposed as Task results. + + params: + - name: repoUrl + type: string + description: The Git repository URL to clone. + + - name: revision + type: string + default: "" + description: The branch or commit SHA to check out. If empty, default branch will be used. + + - name: refspec + type: string + default: "" + description: Refspec to fetch before checking out revision. + + - name: submodules + type: string + default: "true" + description: Initialize and fetch git submodules. + + - name: depth + type: string + default: "1" + description: Perform a shallow clone, fetching only the most recent N commits. + + - name: sslVerify + type: string + default: "true" + description: | + Set the `http.sslVerify` global git config. + Setting this to `false` is not advised unless you are sure that you trust your git remote. + + - name: crtFileName + type: string + default: "ca-bundle.crt" + description: file name of mounted crt using ssl-ca-directory workspace. + + - name: subdirectory + type: string + default: "" + description: Subdirectory inside the `output` Workspace to clone the repo into. + + - name: sparseCheckoutDirectories + type: string + default: "" + description: Define the directory patterns to match or exclude when performing a sparse checkout. + + - name: deleteExisting + type: string + default: "true" + description: Clean out the contents of the destination directory if it already exists before cloning. + + - name: httpProxy + type: string + default: "" + description: HTTP proxy server for non-SSL requests. + + - name: httpsProxy + type: string + default: "" + description: HTTPS proxy server for SSL requests. + + - name: noProxy + type: string + default: "" + description: Opt out of proxying HTTP/HTTPS requests. + + - name: verbose + type: string + default: "true" + description: Log the commands that are executed during `git-clone`'s operation. + + - name: gitInitImage + type: string + default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2" + description: The image providing the git-init binary that this Task runs. + + - name: userHome + type: string + default: "/home/git" + description: Absolute path to the user's home directory. + workspaces: - name: output - description: The git repo will be cloned onto the volume backing this Workspace. + description: The workspace where the repository will be cloned. + - name: ssh-directory optional: true description: | - A .ssh directory with private key, known_hosts, config, etc. Copied to - the user's home before git commands are executed. Used to authenticate - with the git remote when performing the clone. Binding a Secret to this - Workspace is strongly recommended over other volume types. + A .ssh directory with private key, known_hosts, config, etc. + Copied to the user's home before git commands are executed. + - name: basic-auth optional: true description: | - A Workspace containing a .gitconfig and .git-credentials file. These - will be copied to the user's home before any git commands are run. Any - other files in this Workspace are ignored. It is strongly recommended - to use ssh-directory over basic-auth whenever possible and to bind a - Secret to this Workspace over other volume types. + A Workspace containing a .gitconfig and .git-credentials file. + - name: ssl-ca-directory optional: true description: | - A workspace containing CA certificates, this will be used by Git to - verify the peer with when fetching or pushing over HTTPS. - params: - - name: url - description: Repository URL to clone from. - type: string - - name: revision - description: Revision to checkout. (branch, tag, sha, ref, etc...) - type: string - default: "" - - name: refspec - description: Refspec to fetch before checking out revision. - default: "" - - name: submodules - description: Initialize and fetch git submodules. - type: string - default: "true" - - name: depth - description: Perform a shallow clone, fetching only the most recent N commits. - type: string - default: "1" - - name: sslVerify - description: Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote. - type: string - default: "true" - - name: crtFileName - description: file name of mounted crt using ssl-ca-directory workspace. default value is ca-bundle.crt. - type: string - default: "ca-bundle.crt" - - name: subdirectory - description: Subdirectory inside the `output` Workspace to clone the repo into. - type: string - default: "" - - name: sparseCheckoutDirectories - description: Define the directory patterns to match or exclude when performing a sparse checkout. - type: string - default: "" - - name: deleteExisting - description: Clean out the contents of the destination directory if it already exists before cloning. - type: string - default: "true" - - name: httpProxy - description: HTTP proxy server for non-SSL requests. - type: string - default: "" - - name: httpsProxy - description: HTTPS proxy server for SSL requests. - type: string - default: "" - - name: noProxy - description: Opt out of proxying HTTP/HTTPS requests. - type: string - default: "" - - name: verbose - description: Log the commands that are executed during `git-clone`'s operation. - type: string - default: "true" - - name: gitInitImage - description: The image providing the git-init binary that this Task runs. - type: string - default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2" - - name: userHome - description: | - Absolute path to the user's home directory. - type: string - default: "/home/git" + A workspace containing CA certificates, used by Git for SSL verification. + + results: - name: commit description: The precise commit SHA that was fetched by this Task. @@ -97,129 +118,84 @@ spec: description: The precise URL that was fetched by this Task. - name: committer-date description: The epoch timestamp of the commit that was fetched by this Task. + steps: - name: clone - image: "$(params.gitInitImage)" + image: $(params.gitInitImage) env: - - name: HOME - value: "$(params.userHome)" - - name: PARAM_URL - value: $(params.url) - - name: PARAM_REVISION - value: $(params.revision) - - name: PARAM_REFSPEC - value: $(params.refspec) - - name: PARAM_SUBMODULES - value: $(params.submodules) - - name: PARAM_DEPTH - value: $(params.depth) - - name: PARAM_SSL_VERIFY - value: $(params.sslVerify) - - name: PARAM_CRT_FILENAME - value: $(params.crtFileName) - - name: PARAM_SUBDIRECTORY - value: $(params.subdirectory) - - name: PARAM_DELETE_EXISTING - value: $(params.deleteExisting) - - name: PARAM_HTTP_PROXY - value: $(params.httpProxy) - - name: PARAM_HTTPS_PROXY - value: $(params.httpsProxy) - - name: PARAM_NO_PROXY - value: $(params.noProxy) - - name: PARAM_VERBOSE - value: $(params.verbose) - - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES - value: $(params.sparseCheckoutDirectories) - - name: PARAM_USER_HOME - value: $(params.userHome) - - name: WORKSPACE_OUTPUT_PATH - value: $(workspaces.output.path) - - name: WORKSPACE_SSH_DIRECTORY_BOUND - value: $(workspaces.ssh-directory.bound) - - name: WORKSPACE_SSH_DIRECTORY_PATH - value: $(workspaces.ssh-directory.path) - - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND - value: $(workspaces.basic-auth.bound) - - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH - value: $(workspaces.basic-auth.path) - - name: WORKSPACE_SSL_CA_DIRECTORY_BOUND - value: $(workspaces.ssl-ca-directory.bound) - - name: WORKSPACE_SSL_CA_DIRECTORY_PATH - value: $(workspaces.ssl-ca-directory.path) - securityContext: - runAsNonRoot: true - runAsUser: 65532 + - name: HOME + value: $(params.userHome) + - name: SSL_CERT_FILE + value: "/workspace/ssl-ca-directory/$(params.crtFileName)" + - name: HTTP_PROXY + value: $(params.httpProxy) + - name: HTTPS_PROXY + value: $(params.httpsProxy) + - name: NO_PROXY + value: $(params.noProxy) script: | - #!/usr/bin/env sh + #!/bin/sh set -eu - if [ "${PARAM_VERBOSE}" = "true" ] ; then - set -x + echo "[INFO] Preparing home and auth setup..." + mkdir -p $(params.userHome)/.ssh + + if [ -d "/workspace/ssh-directory" ]; then + cp -R /workspace/ssh-directory/* $(params.userHome)/.ssh/ + chmod 700 $(params.userHome)/.ssh + chmod 600 $(params.userHome)/.ssh/* fi - if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then - cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials" - cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig" - chmod 400 "${PARAM_USER_HOME}/.git-credentials" - chmod 400 "${PARAM_USER_HOME}/.gitconfig" + if [ -d "/workspace/basic-auth" ]; then + cp /workspace/basic-auth/.gitconfig $(params.userHome)/.gitconfig || true + cp /workspace/basic-auth/.git-credentials $(params.userHome)/.git-credentials || true fi - if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then - cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh - chmod 700 "${PARAM_USER_HOME}"/.ssh - chmod -R 400 "${PARAM_USER_HOME}"/.ssh/* + if [ "$(params.sslVerify)" = "false" ]; then + echo "[INFO] Disabling SSL verification" + git config --global http.sslVerify false fi - if [ "${WORKSPACE_SSL_CA_DIRECTORY_BOUND}" = "true" ] ; then - export GIT_SSL_CAPATH="${WORKSPACE_SSL_CA_DIRECTORY_PATH}" - if [ "${PARAM_CRT_FILENAME}" != "" ] ; then - export GIT_SSL_CAINFO="${WORKSPACE_SSL_CA_DIRECTORY_PATH}/${PARAM_CRT_FILENAME}" - fi - fi - CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}" + cd /workspace/output - cleandir() { - # Delete any existing contents of the repo directory if it exists. - # - # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/" - # or the root of a mounted volume. - if [ -d "${CHECKOUT_DIR}" ] ; then - # Delete non-hidden files and directories - rm -rf "${CHECKOUT_DIR:?}"/* - # Delete files and directories starting with . but excluding .. - rm -rf "${CHECKOUT_DIR}"/.[!.]* - # Delete files and directories starting with .. plus any other character - rm -rf "${CHECKOUT_DIR}"/..?* - fi - } - - if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then - cleandir || true + CLONE_DIR="$(params.subdirectory)" + if [ -z "$CLONE_DIR" ]; then + CLONE_DIR="." fi - test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}" - test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}" - test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}" - - git config --global --add safe.directory "${WORKSPACE_OUTPUT_PATH}" - /ko-app/git-init \ - -url="${PARAM_URL}" \ - -revision="${PARAM_REVISION}" \ - -refspec="${PARAM_REFSPEC}" \ - -path="${CHECKOUT_DIR}" \ - -sslVerify="${PARAM_SSL_VERIFY}" \ - -submodules="${PARAM_SUBMODULES}" \ - -depth="${PARAM_DEPTH}" \ - -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}" - cd "${CHECKOUT_DIR}" - - RESULT_SHA="$(git rev-parse HEAD)" - EXIT_CODE="$?" - if [ "${EXIT_CODE}" != 0 ] ; then - exit "${EXIT_CODE}" + if [ "$(params.deleteExisting)" = "true" ] && [ -d "$CLONE_DIR" ]; then + echo "[INFO] Deleting existing directory $CLONE_DIR" + rm -rf "$CLONE_DIR" fi - RESULT_COMMITTER_DATE="$(git log -1 --pretty=%ct)" - printf "%s" "${RESULT_COMMITTER_DATE}" > "$(results.committer-date.path)" - printf "%s" "${RESULT_SHA}" > "$(results.commit.path)" - printf "%s" "${PARAM_URL}" > "$(results.url.path)" \ No newline at end of file + + echo "[INFO] Cloning repository..." + git clone --depth=$(params.depth) $(params.repoUrl) "$CLONE_DIR" + cd "$CLONE_DIR" + + if [ -n "$(params.refspec)" ]; then + git fetch origin $(params.refspec) + fi + + if [ -n "$(params.revision)" ]; then + echo "[INFO] Checking out revision: $(params.revision)" + git checkout $(params.revision) || git checkout -b $(params.revision) origin/$(params.revision) || echo "[WARN] Failed to checkout revision" + fi + + if [ "$(params.submodules)" = "true" ]; then + echo "[INFO] Initializing submodules..." + git submodule update --init --recursive + fi + + if [ -n "$(params.sparseCheckoutDirectories)" ]; then + echo "[INFO] Setting up sparse checkout..." + git config core.sparseCheckout true + echo "$(params.sparseCheckoutDirectories)" > .git/info/sparse-checkout + git read-tree -mu HEAD + fi + + echo "[INFO] Writing Task results..." + echo -n "$(git rev-parse HEAD)" > $(results.commit.path) + echo -n "$(git config --get remote.origin.url)" > $(results.url.path) + echo -n "$(git show -s --format=%ct HEAD)" > $(results.committer-date.path) + + echo "[INFO] Clone and checkout complete"