diff --git a/changelogs/fragments/82792-sort entries in FILES_json.yml b/changelogs/fragments/82792-sort entries in FILES_json.yml new file mode 100644 index 00000000000..48917d28235 --- /dev/null +++ b/changelogs/fragments/82792-sort entries in FILES_json.yml @@ -0,0 +1,2 @@ +minor_changes: + - "sort the FILES.json for ansible galaxy build based on name with ASCII2 ordering (https://github.com/ansible/ansible/issues/82792)." diff --git a/lib/ansible/galaxy/collection/__init__.py b/lib/ansible/galaxy/collection/__init__.py index 433af9f5efa..e0fc665d2d4 100644 --- a/lib/ansible/galaxy/collection/__init__.py +++ b/lib/ansible/galaxy/collection/__init__.py @@ -1171,7 +1171,7 @@ def _build_files_manifest_distlib(b_collection_path, namespace, name, manifest_c ) manifest['files'].append(manifest_entry) - + manifest["files"].sort(key=lambda x: x["name"]) return manifest @@ -1244,6 +1244,7 @@ def _build_files_manifest_walk(b_collection_path, namespace, name, ignore_patter ) _walk(b_collection_path, b_collection_path) + manifest["files"].sort(key=lambda x: x["name"]) return manifest @@ -1288,7 +1289,7 @@ def _build_collection_tar( file_manifest, # type: FilesManifestType ): # type: (...) -> str """Build a tar.gz collection artifact from the manifest data.""" - files_manifest_json = to_bytes(json.dumps(file_manifest, indent=True), errors='surrogate_or_strict') + files_manifest_json = to_bytes(json.dumps(file_manifest, indent=True, sort_keys=True), errors='surrogate_or_strict') collection_manifest['file_manifest_file']['chksum_sha256'] = secure_hash_s(files_manifest_json, hash_func=sha256) collection_manifest_json = to_bytes(json.dumps(collection_manifest, indent=True), errors='surrogate_or_strict') diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/build.yml b/test/integration/targets/ansible-galaxy-collection/tasks/build.yml index 83e9acc934f..924cf834d1c 100644 --- a/test/integration/targets/ansible-galaxy-collection/tasks/build.yml +++ b/test/integration/targets/ansible-galaxy-collection/tasks/build.yml @@ -77,6 +77,60 @@ - '"use --force to re-create the collection artifact" in build_existing_no_force.stderr' - '"Created collection for ansible_test.my_collection" in build_existing_force.stdout' +- name: Extract the path to the built artifact + set_fact: + artifact_path: "{{ build_existing_force.stdout_lines | select('search', 'Created collection for ansible_test.my_collection at ') | map('regex_replace', '.* at (.*)$', '\\1') | first }}" + +- name: Define extraction path + set_fact: + extraction_path: "/tmp/new_ansible_collections_extraction" + +- name: Ensure extraction directory exists + file: + path: "{{ extraction_path }}" + state: directory + mode: '0755' + +- name: Extract collection artifact + unarchive: + src: "{{ artifact_path }}" + dest: "{{ extraction_path }}" + remote_src: yes + +- name: Slurp FILES.json content + slurp: + src: "/tmp/new_ansible_collections_extraction/FILES.json" + register: files_content + +- name: Decode FILES.json content + set_fact: + decoded_files_json: "{{ files_content['content'] | b64decode | from_json }}" + + +- name: Set expected order of file names in FILES.json + set_fact: + expected_files_order: [ + ".", + "README.md", + "docs", + "meta", + "meta/runtime.yml", + "plugins", + "plugins/README.md", + "roles" + ] + +- name: Set files_names for later use + set_fact: + files_names: "{{ decoded_files_json['files'] | map(attribute='name') | list }}" + +- name: Assert that files are sorted in the predefined ASCII order + assert: + that: + - files_names == expected_files_order + fail_msg: "The files are not sorted in the predefined ASCII order." + success_msg: "The files are sorted in the predefined ASCII order." + - name: build collection containing ignored files command: ansible-galaxy collection build args: