mirror of
https://github.com/ansible-collections/community.docker.git
synced 2026-06-22 14:01:12 +00:00
Compare commits
No commits in common. "main" and "5.2.1" have entirely different histories.
@ -37,116 +37,293 @@ variables:
|
||||
- name: coverageBranches
|
||||
value: main
|
||||
- name: entryPoint
|
||||
value: tests/utils/shippable/nox.sh
|
||||
- name: prepareEntryPoint
|
||||
value: tests/utils/shippable/nox-prepare.sh
|
||||
value: tests/utils/shippable/shippable.sh
|
||||
- name: fetchDepth
|
||||
value: 0
|
||||
|
||||
resources:
|
||||
containers:
|
||||
- container: default
|
||||
image: quay.io/ansible/azure-pipelines-test-container:8.0.0
|
||||
image: quay.io/ansible/azure-pipelines-test-container:7.0.0
|
||||
|
||||
pool: Standard
|
||||
|
||||
stages:
|
||||
- stage: remote_2_19
|
||||
displayName: Remote 2.19
|
||||
|
||||
### Sanity & units
|
||||
- stage: Ansible_devel
|
||||
displayName: Sanity & Units devel
|
||||
dependsOn: []
|
||||
variables:
|
||||
entryPoint: tests/utils/shippable/nox.sh
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: Ubuntu 22.04 + group 1
|
||||
test: ansible-test-integration-2.19-ubuntu-22.04-azp-1
|
||||
- name: Ubuntu 22.04 + group 2
|
||||
test: ansible-test-integration-2.19-ubuntu-22.04-azp-2
|
||||
- name: Ubuntu 22.04 + group 3
|
||||
test: ansible-test-integration-2.19-ubuntu-22.04-azp-3
|
||||
- name: Ubuntu 22.04 + group 4
|
||||
test: ansible-test-integration-2.19-ubuntu-22.04-azp-4
|
||||
- name: Ubuntu 22.04 + group 5
|
||||
test: ansible-test-integration-2.19-ubuntu-22.04-azp-5
|
||||
|
||||
- stage: remote_2_20
|
||||
displayName: Remote 2.20
|
||||
- name: Sanity
|
||||
test: 'devel/sanity/1'
|
||||
- name: Units
|
||||
test: 'devel/units/1'
|
||||
- stage: Ansible_2_21
|
||||
displayName: Sanity & Units 2.21
|
||||
dependsOn: []
|
||||
variables:
|
||||
entryPoint: tests/utils/shippable/nox.sh
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: RHEL 9.7 + group 1
|
||||
test: ansible-test-integration-2.20-rhel-9.7-azp-1
|
||||
- name: RHEL 9.7 + group 2
|
||||
test: ansible-test-integration-2.20-rhel-9.7-azp-2
|
||||
- name: RHEL 9.7 + group 3
|
||||
test: ansible-test-integration-2.20-rhel-9.7-azp-3
|
||||
- name: RHEL 9.7 + group 4
|
||||
test: ansible-test-integration-2.20-rhel-9.7-azp-4
|
||||
- name: RHEL 9.7 + group 5
|
||||
test: ansible-test-integration-2.20-rhel-9.7-azp-5
|
||||
|
||||
- stage: remote_2_21
|
||||
displayName: Remote 2.21
|
||||
- name: Sanity
|
||||
test: '2.21/sanity/1'
|
||||
- name: Units
|
||||
test: '2.21/units/1'
|
||||
- stage: Ansible_2_20
|
||||
displayName: Sanity & Units 2.20
|
||||
dependsOn: []
|
||||
variables:
|
||||
entryPoint: tests/utils/shippable/nox.sh
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: RHEL 10.1 + group 1
|
||||
test: ansible-test-integration-2.21-rhel-10.1-azp-1
|
||||
- name: RHEL 10.1 + group 2
|
||||
test: ansible-test-integration-2.21-rhel-10.1-azp-2
|
||||
- name: RHEL 10.1 + group 3
|
||||
test: ansible-test-integration-2.21-rhel-10.1-azp-3
|
||||
- name: RHEL 10.1 + group 4
|
||||
test: ansible-test-integration-2.21-rhel-10.1-azp-4
|
||||
- name: RHEL 10.1 + group 5
|
||||
test: ansible-test-integration-2.21-rhel-10.1-azp-5
|
||||
- name: Sanity
|
||||
test: '2.20/sanity/1'
|
||||
- name: Units
|
||||
test: '2.20/units/1'
|
||||
- stage: Ansible_2_19
|
||||
displayName: Sanity & Units 2.19
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: Sanity
|
||||
test: '2.19/sanity/1'
|
||||
- name: Units
|
||||
test: '2.19/units/1'
|
||||
- stage: Ansible_2_18
|
||||
displayName: Sanity & Units 2.18
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: Sanity
|
||||
test: '2.18/sanity/1'
|
||||
- name: Units
|
||||
test: '2.18/units/1'
|
||||
|
||||
- stage: remote_devel
|
||||
### Docker
|
||||
- stage: Docker_devel
|
||||
displayName: Docker devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 44
|
||||
test: fedora44
|
||||
- name: Ubuntu 26.04
|
||||
test: ubuntu2604
|
||||
- name: Ubuntu 24.04
|
||||
test: ubuntu2404
|
||||
- name: Alpine 3.23
|
||||
test: alpine323
|
||||
groups:
|
||||
- 4
|
||||
- 5
|
||||
- stage: Docker_2_21
|
||||
displayName: Docker 2.21
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.21/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 43
|
||||
test: fedora43
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu2204
|
||||
- name: Ubuntu 24.04
|
||||
test: ubuntu2404
|
||||
# - name: Alpine 3.23
|
||||
# test: alpine323
|
||||
groups:
|
||||
- 4
|
||||
- 5
|
||||
- stage: Docker_2_20
|
||||
displayName: Docker 2.20
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.20/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 42
|
||||
test: fedora42
|
||||
- name: Alpine 3.22
|
||||
test: alpine322
|
||||
groups:
|
||||
- 4
|
||||
- 5
|
||||
- stage: Docker_2_19
|
||||
displayName: Docker 2.19
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.19/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 41
|
||||
test: fedora41
|
||||
- name: Alpine 3.21
|
||||
test: alpine321
|
||||
groups:
|
||||
- 4
|
||||
- 5
|
||||
- stage: Docker_2_18
|
||||
displayName: Docker 2.18
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.18/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 40
|
||||
test: fedora40
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu2204
|
||||
- name: Alpine 3.20
|
||||
test: alpine320
|
||||
groups:
|
||||
- 4
|
||||
- 5
|
||||
|
||||
### Community Docker
|
||||
- stage: Docker_community_devel
|
||||
displayName: Docker (community images) devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/linux-community/{0}
|
||||
targets:
|
||||
- name: Debian 11 Bullseye
|
||||
test: debian-bullseye/3.9
|
||||
- name: Debian 12 Bookworm
|
||||
test: debian-bookworm/3.11
|
||||
- name: Debian 13 Trixie
|
||||
test: debian-13-trixie/3.13
|
||||
- name: ArchLinux
|
||||
test: archlinux/3.14
|
||||
groups:
|
||||
- 4
|
||||
- 5
|
||||
|
||||
### Remote
|
||||
- stage: Remote_devel
|
||||
displayName: Remote devel
|
||||
dependsOn: []
|
||||
variables:
|
||||
entryPoint: tests/utils/shippable/nox.sh
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/{0}
|
||||
targets:
|
||||
- name: RHEL 10.1 + group 1 + sdk-dev-latest
|
||||
test: ansible-test-integration-devel-rhel-10.1-azp-1
|
||||
- name: RHEL 10.1 + group 2 + sdk-dev-latest
|
||||
test: ansible-test-integration-devel-rhel-10.1-azp-2
|
||||
- name: RHEL 10.1 + group 3 + sdk-dev-latest
|
||||
test: ansible-test-integration-devel-rhel-10.1-azp-3
|
||||
- name: RHEL 10.1 + group 4 + sdk-dev-latest
|
||||
test: ansible-test-integration-devel-rhel-10.1-azp-4
|
||||
- name: RHEL 10.1 + group 5 + sdk-dev-latest
|
||||
test: ansible-test-integration-devel-rhel-10.1-azp-5
|
||||
- name: RHEL 9.7 + group 1
|
||||
test: ansible-test-integration-devel-rhel-9.7-azp-1
|
||||
- name: RHEL 9.7 + group 2
|
||||
test: ansible-test-integration-devel-rhel-9.7-azp-2
|
||||
- name: RHEL 9.7 + group 3
|
||||
test: ansible-test-integration-devel-rhel-9.7-azp-3
|
||||
- name: RHEL 9.7 + group 4
|
||||
test: ansible-test-integration-devel-rhel-9.7-azp-4
|
||||
- name: RHEL 9.7 + group 5
|
||||
test: ansible-test-integration-devel-rhel-9.7-azp-5
|
||||
- name: RHEL 10.1 with Docker SDK, urllib3, requests from sources
|
||||
test: rhel/10.1-dev-latest
|
||||
- name: RHEL 9.7
|
||||
test: rhel/9.7
|
||||
# For some reason, Ubuntu 24.04 is *extremely* slower than RHEL 9.6
|
||||
# - name: Ubuntu 24.04
|
||||
# test: ubuntu/24.04
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- stage: Remote_2_21
|
||||
displayName: Remote 2.21
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.21/{0}
|
||||
targets:
|
||||
- name: RHEL 10.1
|
||||
test: rhel/10.1
|
||||
# - name: RHEL 9.7
|
||||
# test: rhel/9.7
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- stage: Remote_2_20
|
||||
displayName: Remote 2.20
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.20/{0}
|
||||
targets:
|
||||
- name: RHEL 9.7
|
||||
test: rhel/9.7
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- stage: Remote_2_19
|
||||
displayName: Remote 2.19
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.19/{0}
|
||||
targets:
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu/22.04
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- stage: Remote_2_18
|
||||
displayName: Remote 2.18
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.18/{0}
|
||||
targets:
|
||||
- name: RHEL 9.7
|
||||
test: rhel/9.7
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
|
||||
## Finally
|
||||
|
||||
- stage: Summary
|
||||
condition: succeededOrFailed()
|
||||
dependsOn:
|
||||
- remote_2_19
|
||||
- remote_2_20
|
||||
- remote_2_21
|
||||
- remote_devel
|
||||
- Ansible_devel
|
||||
- Ansible_2_21
|
||||
- Ansible_2_20
|
||||
- Ansible_2_19
|
||||
- Ansible_2_18
|
||||
- Remote_devel
|
||||
- Remote_2_21
|
||||
- Remote_2_20
|
||||
- Remote_2_19
|
||||
- Remote_2_18
|
||||
- Docker_devel
|
||||
- Docker_2_21
|
||||
- Docker_2_20
|
||||
- Docker_2_19
|
||||
- Docker_2_18
|
||||
- Docker_community_devel
|
||||
jobs:
|
||||
- template: templates/coverage.yml
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# Aggregate code coverage results for later processing.
|
||||
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Aggregate code coverage results for later processing.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
agent_temp_directory="$1"
|
||||
@ -13,6 +13,10 @@ PATH="${PWD}/bin:${PATH}"
|
||||
|
||||
mkdir "${agent_temp_directory}/coverage/"
|
||||
|
||||
if [[ "$(ansible --version)" =~ \ 2\.9\. ]]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
options=(--venv --venv-system-site-packages --color -v)
|
||||
|
||||
ansible-test coverage combine --group-by command --export "${agent_temp_directory}/coverage/" "${options[@]}"
|
||||
|
||||
@ -11,7 +11,8 @@ Keep in mind that Azure Pipelines does not enforce unique job display names (onl
|
||||
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
import re
|
||||
@ -23,12 +24,12 @@ def main():
|
||||
"""Main program entry point."""
|
||||
source_directory = sys.argv[1]
|
||||
|
||||
if "/ansible_collections/" in os.getcwd():
|
||||
if '/ansible_collections/' in os.getcwd():
|
||||
output_path = "tests/output"
|
||||
else:
|
||||
output_path = "test/results"
|
||||
|
||||
destination_directory = os.path.join(output_path, "coverage")
|
||||
destination_directory = os.path.join(output_path, 'coverage')
|
||||
|
||||
if not os.path.exists(destination_directory):
|
||||
os.makedirs(destination_directory)
|
||||
@ -37,27 +38,27 @@ def main():
|
||||
count = 0
|
||||
|
||||
for name in os.listdir(source_directory):
|
||||
match = re.search("^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$", name)
|
||||
label = match.group("label")
|
||||
attempt = int(match.group("attempt"))
|
||||
match = re.search('^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$', name)
|
||||
label = match.group('label')
|
||||
attempt = int(match.group('attempt'))
|
||||
jobs[label] = max(attempt, jobs.get(label, 0))
|
||||
|
||||
for label, attempt in jobs.items():
|
||||
name = f"Coverage {attempt} {label}"
|
||||
name = 'Coverage {attempt} {label}'.format(label=label, attempt=attempt)
|
||||
source = os.path.join(source_directory, name)
|
||||
source_files = os.listdir(source)
|
||||
|
||||
for source_file in source_files:
|
||||
source_path = os.path.join(source, source_file)
|
||||
destination_path = os.path.join(destination_directory, source_file + "." + label)
|
||||
print(f'"{source_path}" -> "{destination_path}"')
|
||||
destination_path = os.path.join(destination_directory, source_file + '.' + label)
|
||||
print('"%s" -> "%s"' % (source_path, destination_path))
|
||||
shutil.copyfile(source_path, destination_path)
|
||||
count += 1
|
||||
|
||||
print(f"Coverage file count: {count}")
|
||||
print(f"##vso[task.setVariable variable=coverageFileCount]{count}")
|
||||
print(f"##vso[task.setVariable variable=outputPath]{output_path}")
|
||||
print('Coverage file count: %d' % count)
|
||||
print('##vso[task.setVariable variable=coverageFileCount]%d' % count)
|
||||
print('##vso[task.setVariable variable=outputPath]%s' % output_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check the test results and set variables for use in later steps.
|
||||
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Check the test results and set variables for use in later steps.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
if [[ "$PWD" =~ /ansible_collections/ ]]; then
|
||||
|
||||
@ -15,6 +15,7 @@ import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import typing as t
|
||||
import urllib.request
|
||||
|
||||
|
||||
@ -22,7 +23,7 @@ import urllib.request
|
||||
class CoverageFile:
|
||||
name: str
|
||||
path: pathlib.Path
|
||||
flags: list[str]
|
||||
flags: t.List[str]
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
@ -33,8 +34,8 @@ class Args:
|
||||
|
||||
def parse_args() -> Args:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-n", "--dry-run", action="store_true")
|
||||
parser.add_argument("path", type=pathlib.Path)
|
||||
parser.add_argument('-n', '--dry-run', action='store_true')
|
||||
parser.add_argument('path', type=pathlib.Path)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@ -45,36 +46,32 @@ def parse_args() -> Args:
|
||||
return Args(**kwargs)
|
||||
|
||||
|
||||
def process_files(directory: pathlib.Path) -> tuple[CoverageFile, ...]:
|
||||
def process_files(directory: pathlib.Path) -> t.Tuple[CoverageFile, ...]:
|
||||
processed = []
|
||||
for file in directory.joinpath("reports").glob("coverage*.xml"):
|
||||
name = file.stem.replace("coverage=", "")
|
||||
for file in directory.joinpath('reports').glob('coverage*.xml'):
|
||||
name = file.stem.replace('coverage=', '')
|
||||
|
||||
# Get flags from name
|
||||
flags = name.replace("-powershell", "").split("=") # Drop '-powershell' suffix
|
||||
flags = [
|
||||
flag if not flag.startswith("stub") else flag.split("-")[0] for flag in flags
|
||||
] # Remove "-01" from stub files
|
||||
flags = name.replace('-powershell', '').split('=') # Drop '-powershell' suffix
|
||||
flags = [flag if not flag.startswith('stub') else flag.split('-')[0] for flag in flags] # Remove "-01" from stub files
|
||||
|
||||
processed.append(CoverageFile(name, file, flags))
|
||||
|
||||
return tuple(processed)
|
||||
|
||||
|
||||
def upload_files(codecov_bin: pathlib.Path, files: tuple[CoverageFile, ...], dry_run: bool = False) -> None:
|
||||
def upload_files(codecov_bin: pathlib.Path, files: t.Tuple[CoverageFile, ...], dry_run: bool = False) -> None:
|
||||
for file in files:
|
||||
cmd = [
|
||||
str(codecov_bin),
|
||||
"--name",
|
||||
file.name,
|
||||
"--file",
|
||||
str(file.path),
|
||||
'--name', file.name,
|
||||
'--file', str(file.path),
|
||||
]
|
||||
for flag in file.flags:
|
||||
cmd.extend(["--flags", flag])
|
||||
cmd.extend(['--flags', flag])
|
||||
|
||||
if dry_run:
|
||||
print(f"DRY-RUN: Would run command: {cmd}")
|
||||
print(f'DRY-RUN: Would run command: {cmd}')
|
||||
continue
|
||||
|
||||
subprocess.run(cmd, check=True)
|
||||
@ -82,11 +79,11 @@ def upload_files(codecov_bin: pathlib.Path, files: tuple[CoverageFile, ...], dry
|
||||
|
||||
def download_file(url: str, dest: pathlib.Path, flags: int, dry_run: bool = False) -> None:
|
||||
if dry_run:
|
||||
print(f"DRY-RUN: Would download {url} to {dest} and set mode to {flags:o}")
|
||||
print(f'DRY-RUN: Would download {url} to {dest} and set mode to {flags:o}')
|
||||
return
|
||||
|
||||
with urllib.request.urlopen(url) as resp:
|
||||
with dest.open("w+b") as f:
|
||||
with dest.open('w+b') as f:
|
||||
# Read data in chunks rather than all at once
|
||||
shutil.copyfileobj(resp, f, 64 * 1024)
|
||||
|
||||
@ -95,14 +92,14 @@ def download_file(url: str, dest: pathlib.Path, flags: int, dry_run: bool = Fals
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
url = "https://ansible-ci-files.s3.amazonaws.com/codecov/linux/codecov"
|
||||
with tempfile.TemporaryDirectory(prefix="codecov-") as tmpdir:
|
||||
codecov_bin = pathlib.Path(tmpdir) / "codecov"
|
||||
url = 'https://ansible-ci-files.s3.amazonaws.com/codecov/linux/codecov'
|
||||
with tempfile.TemporaryDirectory(prefix='codecov-') as tmpdir:
|
||||
codecov_bin = pathlib.Path(tmpdir) / 'codecov'
|
||||
download_file(url, codecov_bin, 0o755, args.dry_run)
|
||||
|
||||
files = process_files(args.path)
|
||||
upload_files(codecov_bin, files, args.dry_run)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@ -1,14 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Generate code coverage reports for uploading to Azure Pipelines and codecov.io.
|
||||
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Generate code coverage reports for uploading to Azure Pipelines and codecov.io.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
PATH="${PWD}/bin:${PATH}"
|
||||
|
||||
if [[ "$(ansible --version)" =~ \ 2\.9\. ]]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! ansible-test --help >/dev/null 2>&1; then
|
||||
# Install the devel version of ansible-test for generating code coverage reports.
|
||||
# This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
|
||||
|
||||
@ -1,22 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Configure the test environment and run the tests.
|
||||
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Configure the test environment and run the tests.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
entry_point="$1"
|
||||
test="$2"
|
||||
read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds
|
||||
agent_temp_directory="$4"
|
||||
|
||||
export COMMIT_MESSAGE
|
||||
export COMPLETE
|
||||
export COVERAGE
|
||||
export IS_PULL_REQUEST
|
||||
export COVERAGE_DESTINATION_DIRECTORY="${agent_temp_directory}/coverage"
|
||||
|
||||
if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then
|
||||
IS_PULL_REQUEST=true
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
|
||||
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""
|
||||
|
||||
from __future__ import annotations
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import sys
|
||||
import time
|
||||
@ -15,14 +16,14 @@ def main():
|
||||
"""Main program entry point."""
|
||||
start = time.time()
|
||||
|
||||
sys.stdin.reconfigure(errors="surrogateescape")
|
||||
sys.stdout.reconfigure(errors="surrogateescape")
|
||||
sys.stdin.reconfigure(errors='surrogateescape')
|
||||
sys.stdout.reconfigure(errors='surrogateescape')
|
||||
|
||||
for line in sys.stdin:
|
||||
seconds = int(time.time() - start)
|
||||
sys.stdout.write(f"{seconds // 60:02}:{seconds % 60:02} {line}")
|
||||
seconds = time.time() - start
|
||||
sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@ -23,16 +23,14 @@ jobs:
|
||||
- checkout: self
|
||||
fetchDepth: $(fetchDepth)
|
||||
path: $(checkoutPath)
|
||||
- bash: .azure-pipelines/scripts/run-tests.sh "$(prepareEntryPoint)" "${{ job.test }}" "$(coverageBranches)" "$(Agent.TempDirectory)"
|
||||
displayName: Prepare Tests
|
||||
- bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)" "$(Agent.TempDirectory)"
|
||||
- bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)"
|
||||
displayName: Run Tests
|
||||
- bash: .azure-pipelines/scripts/process-results.sh
|
||||
condition: succeededOrFailed()
|
||||
displayName: Process Results
|
||||
# - bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
|
||||
# condition: eq(variables.haveCoverageData, 'true')
|
||||
# displayName: Aggregate Coverage Data
|
||||
- bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
|
||||
condition: eq(variables.haveCoverageData, 'true')
|
||||
displayName: Aggregate Coverage Data
|
||||
- task: PublishTestResults@2
|
||||
condition: eq(variables.haveTestResults, 'true')
|
||||
inputs:
|
||||
|
||||
2
.github/workflows/docker-images.yml
vendored
2
.github/workflows/docker-images.yml
vendored
@ -45,7 +45,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v7
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
30
.github/workflows/nox.yml
vendored
30
.github/workflows/nox.yml
vendored
@ -15,11 +15,6 @@ name: nox
|
||||
- cron: '0 9 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
# Make sure there is at most one active run per PR, but do not cancel any non-PR runs
|
||||
group: ${{ github.workflow }}-${{ (github.head_ref && github.event.number) || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
nox:
|
||||
uses: ansible-community/antsibull-nox/.github/workflows/reusable-nox-run.yml@main
|
||||
@ -35,6 +30,29 @@ jobs:
|
||||
upload-codecov-pr: false
|
||||
upload-codecov-push: false
|
||||
upload-codecov-schedule: true
|
||||
allow-coverage-cd-override: true
|
||||
max-ansible-core: "2.17"
|
||||
# For some reason GitHub decided to bump Docker on the ubuntu-24.04 image,
|
||||
# which is not compatible with podman and various other things.
|
||||
pre-test-cmd-integration: |-
|
||||
# See https://docs.docker.com/engine/install/ubuntu/.
|
||||
|
||||
# Add Docker's official GPG key:
|
||||
sudo apt update
|
||||
sudo apt install ca-certificates curl
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
# Add the repository to Apt sources:
|
||||
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
|
||||
Types: deb
|
||||
URIs: https://download.docker.com/linux/ubuntu
|
||||
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
|
||||
Components: stable
|
||||
Signed-By: /etc/apt/keyrings/docker.asc
|
||||
EOF
|
||||
|
||||
sudo apt update
|
||||
sudo apt-get install -y --allow-downgrades docker-ce-cli=5:28.0.4-1~ubuntu.24.04~noble docker-ce=5:28.0.4-1~ubuntu.24.04~noble
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
@ -9,10 +9,6 @@
|
||||
"community.internal_test_tools" = "git+https://github.com/ansible-collections/community.internal_test_tools.git,main"
|
||||
"community.library_inventory_filtering_v1" = "git+https://github.com/ansible-collections/community.library_inventory_filtering.git,stable-1"
|
||||
|
||||
[collection_sources_per_ansible.'2.17']
|
||||
# community.general's main branch needs ansible-core >= 2.18
|
||||
"community.general" = "git+https://github.com/ansible-collections/community.general.git,stable-12"
|
||||
|
||||
[vcs]
|
||||
vcs = "git"
|
||||
development_branch = "main"
|
||||
@ -103,28 +99,13 @@ include_devel = true
|
||||
|
||||
[sessions.ansible_test_integration]
|
||||
session_name_template = "ansible-test-integration-{ansible_core}{dash_docker_short}{dash_remote}{dash_python_version}{dash_target_dashized}"
|
||||
display_name_template = "Ⓐ{ansible_core}{plus_docker_nice}{plus_remote_nice}{plus_py_python_version}{plus_target_nice}{plus_force_docker_sdk_for_python_dev}{plus_force_docker_sdk_for_python_pypi}"
|
||||
description_template = "Run integration tests with ansible-core {ansible_core}{comma_docker_nice}{comma_remote_nice}{comma_py_python_version}{comma_target_nice}{comma_force_docker_sdk_for_python_dev}{comma_force_docker_sdk_for_python_pypi}"
|
||||
retry_on_error = "in-ci"
|
||||
display_name_template = "Ⓐ{ansible_core}{plus_docker_short}{plus_remote}{plus_py_python_version}{plus_target}{plus_force_docker_sdk_for_python_dev}{plus_force_docker_sdk_for_python_pypi}"
|
||||
description_template = "Run integration tests with ansible-core {ansible_core}{comma_docker_short}{comma_remote}{comma_py_python_version}{comma_target}{comma_force_docker_sdk_for_python_dev}{comma_force_docker_sdk_for_python_pypi}"
|
||||
|
||||
[sessions.ansible_test_integration.ansible_vars]
|
||||
force_docker_sdk_for_python_dev = { type = "value", value = false, template_value = "" }
|
||||
force_docker_sdk_for_python_pypi = { type = "value", value = false, template_value = "" }
|
||||
|
||||
[sessions.ansible_test_integration.nice_target_names]
|
||||
"azp/1/" = "group 1"
|
||||
"azp/2/" = "group 2"
|
||||
"azp/3/" = "group 3"
|
||||
"azp/4/" = "group 4"
|
||||
"azp/5/" = "group 5"
|
||||
|
||||
[sessions.ansible_test_integration.nice_docker_names]
|
||||
"quay.io/ansible-community/test-image:debian-bullseye" = "Debian 11"
|
||||
"quay.io/ansible-community/test-image:debian-bookworm" = "Debian 12"
|
||||
"quay.io/ansible-community/test-image:debian-13-trixie" = "Debian 13"
|
||||
"quay.io/ansible-community/test-image:archlinux" = "Arch Linux"
|
||||
"quay.io/ansible-community/test-image:opensuse-tumbleweed" = "OpenSuSE Tumbleweed"
|
||||
|
||||
##################################################################################################
|
||||
|
||||
# Ansible-core 2.17:
|
||||
@ -236,12 +217,6 @@ target = [ "azp/4/", "azp/5/" ]
|
||||
python_version = "3.13"
|
||||
docker = "quay.io/ansible-community/test-image:debian-13-trixie"
|
||||
|
||||
[[sessions.ansible_test_integration.groups.sessions]]
|
||||
ansible_core = "devel"
|
||||
target = [ "azp/4/", "azp/5/" ]
|
||||
python_version = "3.13"
|
||||
docker = "quay.io/ansible-community/test-image:opensuse-tumbleweed"
|
||||
|
||||
[[sessions.ansible_test_integration.groups.sessions]]
|
||||
ansible_core = "devel"
|
||||
target = [ "azp/4/", "azp/5/" ]
|
||||
@ -268,14 +243,14 @@ remote = [
|
||||
[sessions.ansible_lint]
|
||||
|
||||
[[sessions.ee_check.execution_environments]]
|
||||
name = "devel-ubi-10"
|
||||
description = "ansible-core devel @ RHEL UBI 10"
|
||||
name = "devel-ubi-9"
|
||||
description = "ansible-core devel @ RHEL UBI 9"
|
||||
test_playbooks = ["tests/ee/all.yml"]
|
||||
config.images.base_image.name = "docker.io/redhat/ubi10:latest"
|
||||
config.images.base_image.name = "docker.io/redhat/ubi9:latest"
|
||||
config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/devel.tar.gz"
|
||||
config.dependencies.ansible_runner.package_pip = "ansible-runner"
|
||||
config.dependencies.python_interpreter.package_system = "python3.14 python3.14-pip python3.14-cryptography"
|
||||
config.dependencies.python_interpreter.python_path = "/usr/bin/python3.14"
|
||||
config.dependencies.python_interpreter.package_system = "python3.12 python3.12-pip python3.12-wheel python3.12-cryptography"
|
||||
config.dependencies.python_interpreter.python_path = "/usr/bin/python3.12"
|
||||
runtime_environment = {"ANSIBLE_PRIVATE_ROLE_VARS" = "true"}
|
||||
runtime_container_options = [
|
||||
# Mount Docker socket into the container so we can talk to Docker outside the container
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
namespace: community
|
||||
name: docker
|
||||
version: 5.3.0
|
||||
version: 5.2.1
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible Docker Working Group
|
||||
|
||||
19
noxfile.py
19
noxfile.py
@ -12,7 +12,6 @@ import nox
|
||||
|
||||
try:
|
||||
import antsibull_nox
|
||||
from antsibull_nox.cli import run as run_antsibull_nox
|
||||
except ImportError:
|
||||
print("You need to install antsibull-nox in the same Python environment as nox.")
|
||||
sys.exit(1)
|
||||
@ -21,24 +20,6 @@ except ImportError:
|
||||
antsibull_nox.load_antsibull_nox_toml()
|
||||
|
||||
|
||||
@nox.session(name="update-azp-config", python=False)
|
||||
def update_azp_config(session: nox.Session) -> None:
|
||||
command = [
|
||||
"antsibull-nox",
|
||||
"update-azp-config",
|
||||
"--exclude-tags",
|
||||
"docker",
|
||||
"--min-ansible-core",
|
||||
"2.19",
|
||||
]
|
||||
if antsibull_nox.IN_CI:
|
||||
command.append("--fail-on-change")
|
||||
session.debug(" ".join(command))
|
||||
result = run_antsibull_nox(command)
|
||||
if result != 0:
|
||||
session.error(f"Execution failed with status code {result}")
|
||||
|
||||
|
||||
# Allow to run the noxfile with `python noxfile.py`, `pipx run noxfile.py`, or similar.
|
||||
# Requires nox >= 2025.02.09
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -7,3 +7,4 @@
|
||||
ansible.builtin.file:
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
no_log: true
|
||||
|
||||
@ -20,7 +20,7 @@ from ansible_collections.community.docker.plugins.inventory.docker_containers im
|
||||
)
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from collections.abc import Callable # pragma: no cover
|
||||
from collections.abc import Callable
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", name="templar")
|
||||
|
||||
@ -43,7 +43,7 @@ from ansible_collections.community.docker.tests.unit.plugins.module_utils._api.c
|
||||
from .. import fake_api
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from ansible_collections.community.docker.plugins.module_utils._api.auth import ( # pragma: no cover
|
||||
from ansible_collections.community.docker.plugins.module_utils._api.auth import (
|
||||
AuthConfig,
|
||||
)
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ from ansible_collections.community.docker.tests.unit.plugins.module_utils._api.c
|
||||
from . import fake_stat
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from collections.abc import Callable # pragma: no cover
|
||||
from collections.abc import Callable
|
||||
|
||||
|
||||
CURRENT_VERSION = f"v{DEFAULT_DOCKER_API_VERSION}"
|
||||
|
||||
@ -13,9 +13,9 @@ from ansible_collections.community.docker.plugins.module_utils._copy import (
|
||||
)
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from collections.abc import Sequence # pragma: no cover
|
||||
from collections.abc import Sequence
|
||||
|
||||
T = t.TypeVar("T") # pragma: no cover
|
||||
T = t.TypeVar("T")
|
||||
|
||||
|
||||
def _simple_generator(sequence: Sequence[T]) -> t.Generator[T]:
|
||||
|
||||
@ -61,10 +61,12 @@ def test_archived_image_manifest_extracts_nothing_when_file_not_present(
|
||||
|
||||
|
||||
def test_archived_image_manifest_raises_when_file_not_a_tar() -> None:
|
||||
with pytest.raises(ImageArchiveInvalidException, match=__file__) as exc_info:
|
||||
try:
|
||||
archived_image_manifest(__file__)
|
||||
assert isinstance(exc_info.value.__cause__, tarfile.ReadError)
|
||||
assert str(__file__) in str(exc_info.value)
|
||||
raise AssertionError()
|
||||
except ImageArchiveInvalidException as e:
|
||||
assert isinstance(e.__cause__, tarfile.ReadError)
|
||||
assert str(__file__) in str(e)
|
||||
|
||||
|
||||
def test_archived_image_manifest_raises_when_tar_missing_manifest(
|
||||
@ -72,10 +74,12 @@ def test_archived_image_manifest_raises_when_tar_missing_manifest(
|
||||
) -> None:
|
||||
write_irrelevant_tar(tar_file_name)
|
||||
|
||||
with pytest.raises(ImageArchiveInvalidException) as exc_info:
|
||||
try:
|
||||
archived_image_manifest(tar_file_name)
|
||||
assert isinstance(exc_info.value.__cause__, KeyError)
|
||||
assert "manifest.json" in str(exc_info.value.__cause__)
|
||||
raise AssertionError()
|
||||
except ImageArchiveInvalidException as e:
|
||||
assert isinstance(e.__cause__, KeyError)
|
||||
assert "manifest.json" in str(e.__cause__)
|
||||
|
||||
|
||||
def test_archived_image_manifest_raises_when_manifest_missing_id(
|
||||
@ -85,7 +89,9 @@ def test_archived_image_manifest_raises_when_manifest_missing_id(
|
||||
|
||||
write_imitation_archive_with_manifest(tar_file_name, manifest)
|
||||
|
||||
with pytest.raises(ImageArchiveInvalidException) as exc_info:
|
||||
try:
|
||||
archived_image_manifest(tar_file_name)
|
||||
assert isinstance(exc_info.value.__cause__, KeyError)
|
||||
assert "Config" in str(exc_info.value.__cause__)
|
||||
raise AssertionError()
|
||||
except ImageArchiveInvalidException as e:
|
||||
assert isinstance(e.__cause__, KeyError)
|
||||
assert "Config" in str(e.__cause__)
|
||||
|
||||
@ -17,12 +17,12 @@ from ansible_collections.community.docker.plugins.module_utils._util import (
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
|
||||
class DAMSpec(t.TypedDict): # pragma: no cover
|
||||
class DAMSpec(t.TypedDict):
|
||||
av: dict[str, t.Any]
|
||||
bv: dict[str, t.Any]
|
||||
result: bool
|
||||
|
||||
class Spec(t.TypedDict): # pragma: no cover
|
||||
class Spec(t.TypedDict):
|
||||
a: t.Any
|
||||
b: t.Any
|
||||
method: t.Literal["strict", "ignore", "allow_more_present"]
|
||||
|
||||
@ -21,13 +21,11 @@ from ..test_support.docker_image_archive_stubbing import (
|
||||
)
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from collections.abc import Callable # pragma: no cover
|
||||
from collections.abc import Callable
|
||||
|
||||
|
||||
def assert_no_logging(msg: str) -> t.NoReturn:
|
||||
raise AssertionError(
|
||||
f"Should not have logged anything but logged {msg}"
|
||||
) # pragma: no cover
|
||||
raise AssertionError(f"Should not have logged anything but logged {msg}")
|
||||
|
||||
|
||||
def capture_logging(messages: list[str]) -> Callable[[str], None]:
|
||||
|
||||
@ -12,8 +12,7 @@ from ansible_collections.community.docker.plugins.modules import (
|
||||
docker_swarm_service,
|
||||
)
|
||||
|
||||
docker_errors = pytest.importorskip("docker.errors")
|
||||
APIError = docker_errors.APIError
|
||||
APIError = pytest.importorskip("docker.errors.APIError")
|
||||
|
||||
|
||||
def test_retry_on_out_of_sequence_error(mocker: t.Any) -> None:
|
||||
|
||||
1
tests/utils/shippable/alpine.sh
Symbolic link
1
tests/utils/shippable/alpine.sh
Symbolic link
@ -0,0 +1 @@
|
||||
remote.sh
|
||||
1
tests/utils/shippable/fedora.sh
Symbolic link
1
tests/utils/shippable/fedora.sh
Symbolic link
@ -0,0 +1 @@
|
||||
remote.sh
|
||||
31
tests/utils/shippable/linux-community.sh
Executable file
31
tests/utils/shippable/linux-community.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
declare -a args
|
||||
IFS='/:' read -ra args <<< "$1"
|
||||
|
||||
image="${args[1]}"
|
||||
python="${args[2]}"
|
||||
|
||||
if [ "${#args[@]}" -gt 3 ]; then
|
||||
target="azp/${args[3]}/"
|
||||
else
|
||||
target="azp/"
|
||||
fi
|
||||
|
||||
if [[ "${python}" =~ -pypi-latest$ ]]; then
|
||||
python="${python/-pypi-latest}"
|
||||
echo 'force_docker_sdk_for_python_pypi: true' >> tests/integration/integration_config.yml
|
||||
fi
|
||||
if [[ "${python}" =~ -dev-latest$ ]]; then
|
||||
python="${python/-dev-latest}"
|
||||
echo 'force_docker_sdk_for_python_dev: true' >> tests/integration/integration_config.yml
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
|
||||
--docker "quay.io/ansible-community/test-image:${image}" --python "${python}"
|
||||
30
tests/utils/shippable/linux.sh
Executable file
30
tests/utils/shippable/linux.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
declare -a args
|
||||
IFS='/:' read -ra args <<< "$1"
|
||||
|
||||
image="${args[1]}"
|
||||
|
||||
if [ "${#args[@]}" -gt 2 ]; then
|
||||
target="azp/${args[2]}/"
|
||||
else
|
||||
target="azp/"
|
||||
fi
|
||||
|
||||
if [[ "${image}" =~ -pypi-latest$ ]]; then
|
||||
image="${image/-pypi-latest}"
|
||||
echo 'force_docker_sdk_for_python_pypi: true' >> tests/integration/integration_config.yml
|
||||
fi
|
||||
if [[ "${image}" =~ -dev-latest$ ]]; then
|
||||
image="${image/-dev-latest}"
|
||||
echo 'force_docker_sdk_for_python_dev: true' >> tests/integration/integration_config.yml
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
|
||||
--docker "${image}"
|
||||
@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
nox_session="$1"
|
||||
|
||||
docker images ansible/ansible
|
||||
docker images quay.io/ansible/*
|
||||
docker ps
|
||||
|
||||
for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v -e '^drydock/' -e '^quay.io/ansible/azure-pipelines-test-container:' | sed 's/^.* //'); do
|
||||
docker rm -f "${container}" || true # ignore errors
|
||||
done
|
||||
|
||||
docker ps
|
||||
command -v python
|
||||
python -V
|
||||
|
||||
function retry
|
||||
{
|
||||
# shellcheck disable=SC2034
|
||||
for repetition in 1 2 3; do
|
||||
set +e
|
||||
"$@"
|
||||
result=$?
|
||||
set -e
|
||||
if [ ${result} == 0 ]; then
|
||||
return ${result}
|
||||
fi
|
||||
echo "@* -> ${result}"
|
||||
done
|
||||
echo "Command '@*' failed 3 times!"
|
||||
exit 255
|
||||
}
|
||||
|
||||
command -v pip
|
||||
pip --version
|
||||
pip list --disable-pip-version-check
|
||||
retry pip install https://github.com/ansible-community/antsibull-nox/archive/main.tar.gz --disable-pip-version-check
|
||||
|
||||
export PYTHONIOENCODING='utf-8'
|
||||
|
||||
export FORCE_COLOR=1
|
||||
export ANTSIBULL_NOX_IGNORE_INSTALLED_COLLECTIONS="true"
|
||||
|
||||
if [ "${nox_session}" == "extra-sanity-tests" ]; then
|
||||
nox --verbose --install-only
|
||||
else
|
||||
nox --verbose --install-only -e "${nox_session}"
|
||||
fi
|
||||
@ -1,64 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
nox_session="$1"
|
||||
|
||||
export PYTHONIOENCODING='utf-8'
|
||||
|
||||
if [ -n "${COVERAGE:-}" ]; then
|
||||
# on-demand coverage reporting triggered by setting the COVERAGE environment variable to a non-empty value
|
||||
export COVERAGE="--coverage"
|
||||
elif [[ "${COMMIT_MESSAGE}" =~ ci_coverage ]]; then
|
||||
# on-demand coverage reporting triggered by having 'ci_coverage' in the latest commit message
|
||||
export COVERAGE="--coverage"
|
||||
else
|
||||
# on-demand coverage reporting disabled (default behavior, always-on coverage reporting remains enabled)
|
||||
export COVERAGE="--coverage-check"
|
||||
fi
|
||||
|
||||
if [ -n "${COMPLETE:-}" ]; then
|
||||
# disable change detection triggered by setting the COMPLETE environment variable to a non-empty value
|
||||
export ANTSIBULL_CHANGE_DETECTION=""
|
||||
elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then
|
||||
# disable change detection triggered by having 'ci_complete' in the latest commit message
|
||||
export ANTSIBULL_CHANGE_DETECTION=""
|
||||
elif [ "${IS_PULL_REQUEST:-}" == "true" ]; then
|
||||
# enable change detection for PRs (default behavior)
|
||||
export ANTSIBULL_CHANGE_DETECTION="true"
|
||||
export ANTSIBULL_BASE_BRANCH="${SYSTEM_PULLREQUEST_TARGETBRANCH}"
|
||||
# Create a branch for the current HEAD, which happens to be a merge commit
|
||||
git checkout -b "pull-request-branch"
|
||||
# Name the target branch
|
||||
git branch "${SYSTEM_PULLREQUEST_TARGETBRANCH}" --track "origin/${SYSTEM_PULLREQUEST_TARGETBRANCH}"
|
||||
# Show branches
|
||||
git branch -vv
|
||||
else
|
||||
# disable change detection for pushes and scheduled runs
|
||||
export ANTSIBULL_CHANGE_DETECTION=""
|
||||
fi
|
||||
|
||||
if [[ "${COVERAGE:-}" == "--coverage" ]]; then
|
||||
export ANTSIBULL_NOX_TIMEOUT=60
|
||||
else
|
||||
export ANTSIBULL_NOX_TIMEOUT=50
|
||||
fi
|
||||
|
||||
if [ "${IS_PULL_REQUEST:-}" == "true" ]; then
|
||||
export ANTSIBULL_NOX_INTEGRATION_ALLOW_UNSTABLE_CHANGED="true"
|
||||
fi
|
||||
|
||||
export FORCE_COLOR=1
|
||||
export ANTSIBULL_NOX_IGNORE_INSTALLED_COLLECTIONS="true"
|
||||
export ANTSIBULL_NOX_COVERAGE_DESTINATION="${COVERAGE_DESTINATION_DIRECTORY}"
|
||||
export ANTSIBULL_NOX_COVERAGE_ANALYSIS_FILE="${COVERAGE_DESTINATION_DIRECTORY}/coverage-analyze-targets.json"
|
||||
export ANTSIBULL_NOX_COVERAGE_NO_XML="true"
|
||||
|
||||
if [ "${nox_session}" == "extra-sanity-tests" ]; then
|
||||
nox --reuse-existing-virtualenvs --no-install
|
||||
else
|
||||
nox --reuse-existing-virtualenvs --no-install -e "${nox_session}" -- ${COVERAGE}
|
||||
fi
|
||||
48
tests/utils/shippable/remote.sh
Executable file
48
tests/utils/shippable/remote.sh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
declare -a args
|
||||
IFS='/:' read -ra args <<< "$1"
|
||||
|
||||
platform="${args[0]}"
|
||||
version="${args[1]}"
|
||||
pyver=default
|
||||
|
||||
# check for explicit python version like 8.3@3.8
|
||||
declare -a splitversion
|
||||
IFS='@' read -ra splitversion <<< "$version"
|
||||
|
||||
if [ "${#splitversion[@]}" -gt 1 ]; then
|
||||
version="${splitversion[0]}"
|
||||
pyver="${splitversion[1]}"
|
||||
fi
|
||||
|
||||
if [ "${#args[@]}" -gt 2 ]; then
|
||||
target="azp/${args[2]}/"
|
||||
else
|
||||
target="azp/"
|
||||
fi
|
||||
|
||||
if [[ "${version}" =~ -pypi-latest$ ]]; then
|
||||
version="${version/-pypi-latest}"
|
||||
echo 'force_docker_sdk_for_python_pypi: true' >> tests/integration/integration_config.yml
|
||||
fi
|
||||
if [[ "${version}" =~ -dev-latest$ ]]; then
|
||||
version="${version/-dev-latest}"
|
||||
echo 'force_docker_sdk_for_python_dev: true' >> tests/integration/integration_config.yml
|
||||
fi
|
||||
|
||||
stage="${S:-prod}"
|
||||
provider="${P:-default}"
|
||||
|
||||
if [ "${platform}" == "rhel" ] && [[ "${version}" =~ ^8\. ]]; then
|
||||
echo "pynacl >= 1.4.0, < 1.5.0; python_version == '3.6'" >> tests/utils/constraints.txt
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
|
||||
--python "${pyver}" --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}"
|
||||
1
tests/utils/shippable/rhel.sh
Symbolic link
1
tests/utils/shippable/rhel.sh
Symbolic link
@ -0,0 +1 @@
|
||||
remote.sh
|
||||
17
tests/utils/shippable/sanity.sh
Executable file
17
tests/utils/shippable/sanity.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
if [ "${BASE_BRANCH:-}" ]; then
|
||||
base_branch="origin/${BASE_BRANCH}"
|
||||
else
|
||||
base_branch=""
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
|
||||
--docker --base-branch "${base_branch}" \
|
||||
--allow-disabled
|
||||
234
tests/utils/shippable/shippable.sh
Executable file
234
tests/utils/shippable/shippable.sh
Executable file
@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
declare -a args
|
||||
IFS='/:' read -ra args <<< "$1"
|
||||
|
||||
ansible_version="${args[0]}"
|
||||
script="${args[1]}"
|
||||
after_script="${args[2]}"
|
||||
|
||||
function join {
|
||||
local IFS="$1";
|
||||
shift;
|
||||
echo "$*";
|
||||
}
|
||||
|
||||
# Ensure we can write other collections to this dir
|
||||
sudo chown -R "$(whoami)" "${PWD}/../../../"
|
||||
|
||||
test="$(join / "${args[@]:1}")"
|
||||
|
||||
docker images ansible/ansible
|
||||
docker images quay.io/ansible/*
|
||||
docker ps
|
||||
|
||||
for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v -e '^drydock/' -e '^quay.io/ansible/azure-pipelines-test-container:' | sed 's/^.* //'); do
|
||||
docker rm -f "${container}" || true # ignore errors
|
||||
done
|
||||
|
||||
docker ps
|
||||
|
||||
if [ -d /home/shippable/cache/ ]; then
|
||||
ls -la /home/shippable/cache/
|
||||
fi
|
||||
|
||||
command -v python
|
||||
python -V
|
||||
|
||||
function retry
|
||||
{
|
||||
# shellcheck disable=SC2034
|
||||
for repetition in 1 2 3; do
|
||||
set +e
|
||||
"$@"
|
||||
result=$?
|
||||
set -e
|
||||
if [ ${result} == 0 ]; then
|
||||
return ${result}
|
||||
fi
|
||||
echo "@* -> ${result}"
|
||||
done
|
||||
echo "Command '@*' failed 3 times!"
|
||||
exit 255
|
||||
}
|
||||
|
||||
command -v pip
|
||||
pip --version
|
||||
pip list --disable-pip-version-check
|
||||
if [ "${ansible_version}" == "devel" ]; then
|
||||
retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
||||
else
|
||||
retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
|
||||
fi
|
||||
|
||||
export ANSIBLE_COLLECTIONS_PATHS="${PWD}/../../../"
|
||||
|
||||
# START: HACK
|
||||
|
||||
COMMUNITY_CRYPTO_BRANCH=main
|
||||
if [ "${ansible_version}" == "2.16" ]; then
|
||||
COMMUNITY_CRYPTO_BRANCH=stable-2
|
||||
fi
|
||||
if [ "${script}" == "linux" ] && [ "$after_script" == "ubuntu2004" ]; then
|
||||
COMMUNITY_CRYPTO_BRANCH=stable-2
|
||||
fi
|
||||
|
||||
retry git clone --depth=1 --single-branch --branch stable-1 https://github.com/ansible-collections/community.library_inventory_filtering.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/library_inventory_filtering_v1"
|
||||
# NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429)
|
||||
# retry ansible-galaxy -vvv collection install community.library_inventory_filtering_v1
|
||||
|
||||
if [ "${test}" == "units/1" ]; then
|
||||
# Nothing further should be added to this list.
|
||||
# This is to prevent modules or plugins in this collection having a runtime dependency on other collections.
|
||||
retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/internal_test_tools"
|
||||
# NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429)
|
||||
# retry ansible-galaxy -vvv collection install community.internal_test_tools
|
||||
fi
|
||||
|
||||
if [ "${script}" != "sanity/1" ] && [ "${script}" != "units/1" ]; then
|
||||
# To prevent Python dependencies on other collections only install other collections for integration tests
|
||||
retry git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.posix.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/ansible/posix"
|
||||
retry git clone --depth=1 --single-branch --branch "${COMMUNITY_CRYPTO_BRANCH}" https://github.com/ansible-collections/community.crypto.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/crypto"
|
||||
retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general"
|
||||
# NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429)
|
||||
# retry ansible-galaxy -vvv collection install ansible.posix
|
||||
# retry ansible-galaxy -vvv collection install community.crypto
|
||||
# retry ansible-galaxy -vvv collection install community.general
|
||||
fi
|
||||
# END: HACK
|
||||
|
||||
|
||||
export PYTHONIOENCODING='utf-8'
|
||||
|
||||
if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then
|
||||
COVERAGE=yes
|
||||
COMPLETE=yes
|
||||
fi
|
||||
|
||||
if [ -n "${COVERAGE:-}" ]; then
|
||||
# on-demand coverage reporting triggered by setting the COVERAGE environment variable to a non-empty value
|
||||
export COVERAGE="--coverage"
|
||||
elif [[ "${COMMIT_MESSAGE}" =~ ci_coverage ]]; then
|
||||
# on-demand coverage reporting triggered by having 'ci_coverage' in the latest commit message
|
||||
export COVERAGE="--coverage"
|
||||
else
|
||||
# on-demand coverage reporting disabled (default behavior, always-on coverage reporting remains enabled)
|
||||
export COVERAGE="--coverage-check"
|
||||
fi
|
||||
|
||||
if [ -n "${COMPLETE:-}" ]; then
|
||||
# disable change detection triggered by setting the COMPLETE environment variable to a non-empty value
|
||||
export CHANGED=""
|
||||
elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then
|
||||
# disable change detection triggered by having 'ci_complete' in the latest commit message
|
||||
export CHANGED=""
|
||||
else
|
||||
# enable change detection (default behavior)
|
||||
export CHANGED="--changed"
|
||||
fi
|
||||
|
||||
if [ "${IS_PULL_REQUEST:-}" == "true" ]; then
|
||||
# run unstable tests which are targeted by focused changes on PRs
|
||||
export UNSTABLE="--allow-unstable-changed"
|
||||
else
|
||||
# do not run unstable tests outside PRs
|
||||
export UNSTABLE=""
|
||||
fi
|
||||
|
||||
# remove empty core/extras module directories from PRs created prior to the repo-merge
|
||||
find plugins -type d -empty -print -delete
|
||||
|
||||
function cleanup
|
||||
{
|
||||
# for complete on-demand coverage generate a report for all files with no coverage on the "sanity/5" job so we only have one copy
|
||||
if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ] && [ "${test}" == "sanity/5" ]; then
|
||||
stub="--stub"
|
||||
# trigger coverage reporting for stubs even if no other coverage data exists
|
||||
mkdir -p tests/output/coverage/
|
||||
else
|
||||
stub=""
|
||||
fi
|
||||
|
||||
if [ -d tests/output/coverage/ ]; then
|
||||
if find tests/output/coverage/ -mindepth 1 -name '.*' -prune -o -print -quit | grep -q .; then
|
||||
process_coverage='yes' # process existing coverage files
|
||||
elif [ "${stub}" ]; then
|
||||
process_coverage='yes' # process coverage when stubs are enabled
|
||||
else
|
||||
process_coverage=''
|
||||
fi
|
||||
|
||||
if [ "${process_coverage}" ]; then
|
||||
# use python 3.7 for coverage to avoid running out of memory during coverage xml processing
|
||||
# only use it for coverage to avoid the additional overhead of setting up a virtual environment for a potential no-op job
|
||||
virtualenv --python /usr/bin/python3.7 ~/ansible-venv
|
||||
set +ux
|
||||
. ~/ansible-venv/bin/activate
|
||||
set -ux
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ansible-test coverage xml --color -v --requirements --group-by command --group-by version ${stub:+"$stub"}
|
||||
cp -a tests/output/reports/coverage=*.xml "$SHIPPABLE_RESULT_DIR/codecoverage/"
|
||||
|
||||
if [ "${ansible_version}" != "2.9" ]; then
|
||||
# analyze and capture code coverage aggregated by integration test target
|
||||
ansible-test coverage analyze targets generate -v "$SHIPPABLE_RESULT_DIR/testresults/coverage-analyze-targets.json"
|
||||
fi
|
||||
|
||||
# upload coverage report to codecov.io only when using complete on-demand coverage
|
||||
if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ]; then
|
||||
for file in tests/output/reports/coverage=*.xml; do
|
||||
flags="${file##*/coverage=}"
|
||||
flags="${flags%-powershell.xml}"
|
||||
flags="${flags%.xml}"
|
||||
# remove numbered component from stub files when converting to tags
|
||||
flags="${flags//stub-[0-9]*/stub}"
|
||||
flags="${flags//=/,}"
|
||||
flags="${flags//[^a-zA-Z0-9_,]/_}"
|
||||
|
||||
bash <(curl -s https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh) \
|
||||
-f "${file}" \
|
||||
-F "${flags}" \
|
||||
-n "${test}" \
|
||||
-t 8450ed26-4e94-4d07-8831-d2023d6d20a3 \
|
||||
-X coveragepy \
|
||||
-X gcov \
|
||||
-X fix \
|
||||
-X search \
|
||||
-X xcode \
|
||||
|| echo "Failed to upload code coverage report to codecov.io: ${file}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d tests/output/junit/ ]; then
|
||||
cp -aT tests/output/junit/ "$SHIPPABLE_RESULT_DIR/testresults/"
|
||||
fi
|
||||
|
||||
if [ -d tests/output/data/ ]; then
|
||||
cp -a tests/output/data/ "$SHIPPABLE_RESULT_DIR/testresults/"
|
||||
fi
|
||||
|
||||
if [ -d tests/output/bot/ ]; then
|
||||
cp -aT tests/output/bot/ "$SHIPPABLE_RESULT_DIR/testresults/"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${SHIPPABLE_BUILD_ID:-}" ]; then trap cleanup EXIT; fi
|
||||
|
||||
if [[ "${COVERAGE:-}" == "--coverage" ]]; then
|
||||
timeout=60
|
||||
else
|
||||
timeout=50
|
||||
fi
|
||||
|
||||
ansible-test env --dump --show --timeout "${timeout}" --color -v
|
||||
|
||||
if [ "${SHIPPABLE_BUILD_ID:-}" ]; then "tests/utils/shippable/check_matrix.py"; fi
|
||||
"tests/utils/shippable/${script}.sh" "${test}"
|
||||
1
tests/utils/shippable/ubuntu.sh
Symbolic link
1
tests/utils/shippable/ubuntu.sh
Symbolic link
@ -0,0 +1 @@
|
||||
remote.sh
|
||||
29
tests/utils/shippable/units.sh
Executable file
29
tests/utils/shippable/units.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -o pipefail -eux
|
||||
|
||||
declare -a args
|
||||
IFS='/:' read -ra args <<< "$1"
|
||||
|
||||
group="${args[1]}"
|
||||
|
||||
if [[ "${COVERAGE:-}" == "--coverage" ]]; then
|
||||
timeout=90
|
||||
else
|
||||
timeout=30
|
||||
fi
|
||||
|
||||
group1=()
|
||||
|
||||
case "${group}" in
|
||||
1) options=("${group1[@]:+${group1[@]}}") ;;
|
||||
esac
|
||||
|
||||
ansible-test env --timeout "${timeout}" --color -v
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ansible-test units --color -v --docker default ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
|
||||
"${options[@]:+${options[@]}}" \
|
||||
Loading…
Reference in New Issue
Block a user