galaxy: Add license_file to manifest directives (#79420)

* galaxy: Add license_file to manifest directives

* ag collection build: Test license handling

This adds tests to ensure that
    - REUSE licensing files: .reuse/dep5, LICENSES/*, anyfile.license
    - galaxy.yml license_file
are always included in the manifest.
pull/56508/merge
Maxwell G 2 years ago committed by GitHub
parent 5f3a6b78db
commit ab76916b14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,4 @@
---
minor_changes:
- galaxy - include ``license_file`` in the default manifest directives
(https://github.com/ansible/ansible/pull-request/79420)

@ -479,6 +479,7 @@ def build_collection(u_collection_path, u_output_path, force):
collection_meta['name'], # type: ignore[arg-type]
collection_meta['build_ignore'], # type: ignore[arg-type]
collection_meta['manifest'], # type: ignore[arg-type]
collection_meta['license_file'], # type: ignore[arg-type]
)
artifact_tarball_file_name = '{ns!s}-{name!s}-{ver!s}.tar.gz'.format(
@ -1062,8 +1063,9 @@ def _make_entry(name, ftype, chksum_type='sha256', chksum=None):
}
def _build_files_manifest(b_collection_path, namespace, name, ignore_patterns, manifest_control):
# type: (bytes, str, str, list[str], dict[str, t.Any]) -> FilesManifestType
def _build_files_manifest(b_collection_path, namespace, name, ignore_patterns,
manifest_control, license_file):
# type: (bytes, str, str, list[str], dict[str, t.Any], t.Optional[str]) -> FilesManifestType
if ignore_patterns and manifest_control is not Sentinel:
raise AnsibleError('"build_ignore" and "manifest" are mutually exclusive')
@ -1073,14 +1075,15 @@ def _build_files_manifest(b_collection_path, namespace, name, ignore_patterns, m
namespace,
name,
manifest_control,
license_file,
)
return _build_files_manifest_walk(b_collection_path, namespace, name, ignore_patterns)
def _build_files_manifest_distlib(b_collection_path, namespace, name, manifest_control):
# type: (bytes, str, str, dict[str, t.Any]) -> FilesManifestType
def _build_files_manifest_distlib(b_collection_path, namespace, name, manifest_control,
license_file):
# type: (bytes, str, str, dict[str, t.Any], t.Optional[str]) -> FilesManifestType
if not HAS_DISTLIB:
raise AnsibleError('Use of "manifest" requires the python "distlib" library')
@ -1124,6 +1127,9 @@ def _build_files_manifest_distlib(b_collection_path, namespace, name, manifest_c
'recursive-include plugins */**.py */**.license',
])
if license_file:
directives.append(f'include {license_file}')
plugins = set(l.package.split('.')[-1] for d, l in get_all_plugin_loaders())
for plugin in sorted(plugins):
if plugin in ('modules', 'module_utils'):
@ -1585,6 +1591,7 @@ def install_src(collection, b_collection_path, b_collection_output_path, artifac
collection_meta['namespace'], collection_meta['name'],
collection_meta['build_ignore'],
collection_meta['manifest'],
collection_meta['license_file'],
)
collection_output_path = _build_collection_dir(

@ -1,6 +1,11 @@
MANIFEST.json
FILES.json
README.rst
GPL
LICENSES/
LICENSES/MIT.txt
.reuse/
.reuse/dep5
changelogs/
docs/
playbooks/
@ -88,6 +93,7 @@ plugins/test/bar.yml
plugins/test/baz.yaml
plugins/test/test.py
plugins/vars/bar.yml
plugins/vars/bar.yml.license
plugins/vars/baz.yaml
plugins/vars/test.py
roles/foo/

@ -2,6 +2,7 @@ namespace: ns
name: col
version: 1.0.0
readme: README.rst
license_file: GPL
authors:
- Ansible
manifest:

@ -5,8 +5,12 @@ paths = [
'ns-col-1.0.0.tar.gz',
'foo.txt',
'README.rst',
'GPL',
'LICENSES/MIT.txt',
'.reuse/dep5',
'artifacts/.gitkeep',
'plugins/vars/bar.yml',
'plugins/vars/bar.yml.license',
'plugins/vars/baz.yaml',
'plugins/vars/test.py',
'plugins/vars/docs.md',

@ -596,7 +596,7 @@ def test_build_ignore_files_and_folders(collection_input, monkeypatch):
tests_file.write('random')
tests_file.flush()
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel)
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel, None)
assert actual['format'] == 1
for manifest_entry in actual['files']:
@ -632,7 +632,7 @@ def test_build_ignore_older_release_in_root(collection_input, monkeypatch):
file_obj.write('random')
file_obj.flush()
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel)
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel, None)
assert actual['format'] == 1
plugin_release_found = False
@ -660,7 +660,7 @@ def test_build_ignore_patterns(collection_input, monkeypatch):
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection',
['*.md', 'plugins/action', 'playbooks/*.j2'],
Sentinel)
Sentinel, None)
assert actual['format'] == 1
expected_missing = [
@ -711,7 +711,7 @@ def test_build_ignore_symlink_target_outside_collection(collection_input, monkey
link_path = os.path.join(input_dir, 'plugins', 'connection')
os.symlink(outside_dir, link_path)
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel)
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel, None)
for manifest_entry in actual['files']:
assert manifest_entry['name'] != 'plugins/connection'
@ -735,7 +735,7 @@ def test_build_copy_symlink_target_inside_collection(collection_input):
os.symlink(roles_target, roles_link)
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel)
actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', [], Sentinel, None)
linked_entries = [e for e in actual['files'] if e['name'].startswith('playbooks/roles/linked')]
assert len(linked_entries) == 1

Loading…
Cancel
Save