diff --git a/README.md b/README.md index a751dff..09ab0d8 100644 --- a/README.md +++ b/README.md @@ -66,19 +66,42 @@ Tracks the commits in a [git](http://git-scm.com/) repository. * `fetch_tags`: *Optional.* If `true` the flag `--tags` will be used to fetch all tags in the repository. If `false` no tags will be fetched. -* `submodule_credentials`: *Optional.* List of credentials for HTTP(s) auth when pulling/pushing private git submodules which are not stored in the same git server as the container repository. - Example: - - ``` +* `submodule_credentials`: *Optional.* List of credentials for HTTP(s) or SSH auth when pulling git submodules which are not stored in the same git server as the container repository or are protected by a different private key. + * http(s) credentials: + * `host` : The host to connect too. Note that `host` is specified with no protocol extensions. + * `username` : Username for HTTP(S) auth when pulling submodule. + * `password` : Password for HTTP(S) auth when pulling submodule. + * ssh credentials: + * `url` : Submodule url, as specified in the `.gitmodule` file. Support full or relative ssh url. + * `private_key` : Private key for SSH auth when pulling submodule. + * `private_key_passphrase` : *Optional.* To unlock `private_key` if it is protected by a passphrase. + * exemple: + ```yaml submodule_credentials: + # http(s) credentials - host: github.com username: git-user password: git-password - - + # ssh credentials + - url: git@github.com:org-name/repo-name.git + private_key: | + -----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEAtCS10/f7W7lkQaSgD/mVeaSOvSF9ql4hf/zfMwfVGgHWjj+W + + DWiJL+OFeg9kawcUL6hQ8JeXPhlImG6RTUffma9+iGQyyBMCGd1l + -----END RSA PRIVATE KEY----- + private_key_passphrase: ssh-passphrase # (optionnal) + # ssh credentials with relative url + - url: ../org-name/repo-name.git + private_key: | + -----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEAtCS10/f7W7lkQaSgD/mVeaSOvSF9ql4hf/zfMwfVGgHWjj+W + + DWiJL+OFeg9kawcUL6hQ8JeXPhlImG6RTUffma9+iGQyyBMCGd1l + -----END RSA PRIVATE KEY----- + private_key_passphrase: ssh-passphrase # (optionnal) ``` - Note that `host` is specified with no protocol extensions. - * `git_config`: *Optional.* If specified as (list of pairs `name` and `value`) it will configure git global options, setting each name with each value. @@ -292,7 +315,7 @@ the case. * `.git/commit_message`: For publishing the Git commit message on successful builds. - * `.git/commit_timestamp`: For tagging builds with a timestamp. +* `.git/commit_timestamp`: For tagging builds with a timestamp. * `.git/describe_ref`: Version reference detected and checked out. Can be templated with `describe_ref_options` parameter. By default, it will contain the `--g` (eg. `v1.6.2-1-g13dfd7b`). diff --git a/assets/common.sh b/assets/common.sh index a5c30ca..bb82e55 100644 --- a/assets/common.sh +++ b/assets/common.sh @@ -12,9 +12,10 @@ load_pubkey() { if [ -s $private_key_path ]; then chmod 0600 $private_key_path - eval $(ssh-agent) >/dev/null 2>&1 - trap "kill $SSH_AGENT_PID" EXIT - SSH_ASKPASS_REQUIRE=force SSH_ASKPASS=$(dirname $0)/askpass.sh GIT_SSH_PRIVATE_KEY_PASS="$passphrase" DISPLAY= ssh-add $private_key_path >/dev/null + # create or re-initialize ssh-agent + init_ssh_agent + + SSH_ASKPASS_REQUIRE=force SSH_ASKPASS=$(dirname $0)/askpass.sh GIT_SSH_PRIVATE_KEY_PASS="$passphrase" DISPLAY= ssh-add $private_key_path > /dev/null mkdir -p ~/.ssh cat > ~/.ssh/config < /dev/null + exit_code=$? + set -e + + if [[ ${exit_code} -eq 2 ]]; then + # ssh-agent does not exist, create ssh-agent + eval $(ssh-agent) > /dev/null 2>&1 + trap "kill $SSH_AGENT_PID" EXIT + else + # ssh-agent exist, remove all identities + ssh-add -D &> /dev/null + fi + +} + configure_https_tunnel() { tunnel=$(jq -r '.source.https_tunnel // empty' <<< "$1") diff --git a/assets/in b/assets/in index 96bea2b..8dd81af 100755 --- a/assets/in +++ b/assets/in @@ -166,6 +166,7 @@ if [ "$submodules" != "none" ]; then sed -e 's/^submodule\.\(.\+\)\.path$/\1/' } | while read submodule_name; do submodule_path="$(git config --file .gitmodules --get "submodule.${submodule_name}.path")" + submodule_url="$(git config --file .gitmodules --get "submodule.${submodule_name}.url")" if [ "$depth" -gt 0 ]; then git config "submodule.${submodule_name}.update" "!$bin_dir/deepen_shallow_clone_until_ref_is_found_then_check_out $depth" @@ -176,7 +177,35 @@ if [ "$submodules" != "none" ]; then continue fi - git submodule update --init --no-fetch $depthflag $submodule_parameters "$submodule_path" + # check for ssh submodule_credentials + submodule_cred=$(jq --arg submodule_url "${submodule_url}" '.source.submodule_credentials // [] | [.[] | select(.url==$submodule_url)] | first // empty' <<< ${payload}) + + if [[ -z ${submodule_cred} ]]; then + + # update normally + git submodule update --init --no-fetch $depthflag $submodule_parameters "$submodule_path" + + else + + # create or re-initialize ssh-agent + init_ssh_agent + + private_key=$(jq -r '.private_key' <<< ${submodule_cred}) + passphrase=$(jq -r '.private_key_passphrase // empty' <<< ${submodule_cred}) + + private_key_path=$(mktemp -t git-resource-submodule-private-key.XXXXXX) + echo "${private_key}" > ${private_key_path} + chmod 0600 ${private_key_path} + + # add submodule private_key identity + SSH_ASKPASS_REQUIRE=force SSH_ASKPASS=$(dirname $0)/askpass.sh GIT_SSH_PRIVATE_KEY_PASS="$passphrase" DISPLAY= ssh-add $private_key_path > /dev/null + + git submodule update --init --no-fetch $depthflag $submodule_parameters "$submodule_path" + + # restore main ssh-agent (if needed) + load_pubkey "${payload}" + + fi if [ "$depth" -gt 0 ]; then git config --unset "submodule.${submodule_name}.update"