zuul-jobs/roles/mirror-workspace-git-repos/tasks/main.yaml
Benjamin Schanzel f18644891d Kubernetes Node Support for Mirroring Git Repos
The `mirror-workspace-git-repos` uses Git to mirror repos from the
executor to build nodes. This comes in handy when the node already
holds a copy of the repo(s), as Git can incrementally update them.
Currently, `mirror-workspace-git-repos` assumes the build node is
directly reachable via ssh. This is (usually) not the case when
running against a Kubernetes Pod build node, thus we can not
efficiently update repos on such nodes using Git.
This change allows pushing Git repos to Kubernetes Pods by bridging
the Git communication over `kubectl` and thereby allowing for the
same behaviour as for standard, non-container, ssh-reachable build
nodes.
(cf. https://git-scm.com/docs/git-remote-ext)

Change-Id: I71919d3bc93e48d5bb24234265fca9c84ce23b87
2020-03-09 14:44:24 +01:00

55 lines
2.3 KiB
YAML

- name: Allow pushing to non-bare repo
git_config:
name: receive.denyCurrentBranch ignore
value: ignore
scope: local
repo: "{{ ansible_user_dir }}/{{ item.value.src_dir }}"
with_dict: "{{ zuul.projects }}"
- name: Synchronize src repos to workspace directory
command: |-
{% if ansible_connection == "kubectl" %}
git push {% if mirror_workspace_quiet %}--quiet{% endif %} --mirror "ext::kubectl -n {{ zuul.resources[inventory_hostname].namespace }} exec -i {{ zuul.resources[inventory_hostname].pod }} -- %S {{ ansible_user_dir }}/{{ item.value.src_dir }}"
{% else %}
git push {% if mirror_workspace_quiet %}--quiet{% endif %} --mirror git+ssh://{{ ansible_user }}@{{ ansible_host | ipwrap }}:{{ ansible_port }}/{{ ansible_user_dir }}/{{ item.value.src_dir }}
{% endif %}
args:
chdir: "{{ zuul.executor.work_root }}/{{ item.value.src_dir }}"
environment:
GIT_ALLOW_PROTOCOL: ext:ssh
with_dict: "{{ zuul.projects }}"
delegate_to: localhost
# We occasionally see git pushes in the middle of this loop fail then
# subsequent pushes for other repos succeed. The entire loop ends up
# failing because one of the pushes failed. Mitigate this by retrying
# on failure.
register: git_push
until: git_push is success
retries: 3
# ANSIBLE0006: Skip linting since it triggers on the "git" command,
# but push is not supported by ansible git module.
tags:
- skip_ansible_lint
# Do this as a multi-line shell so that we can do the loop once
- name: Update remote repository state correctly
shell: |
# Reset is needed because we pushed to a non-bare repo
git reset --hard
# Clean is needed because we pushed to a non-bare repo
git clean -xdf
# Undo the config setting we did above
git config --local --unset receive.denyCurrentBranch
# checkout the branch matching the branch set up by the executor
git checkout {% if mirror_workspace_quiet %}--quiet{% endif %} {{ item.value.checkout }}
# put out a status line with the current HEAD
echo "{{ item.value.canonical_name }} checked out to:"
git log --pretty=oneline -1
args:
chdir: "{{ ansible_user_dir }}/{{ item.value.src_dir }}"
with_dict: "{{ zuul.projects }}"
# ANSIBLE0006: Skip linting since it triggers on the "git" command,
# but we prefer the shell above
tags:
- skip_ansible_lint