This is an automated email from the ASF dual-hosted git repository. sbp pushed a commit to branch sbp in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
commit ca978b985afe94b0360016ec20a6d1a6a1477efa Author: Sean B. Palmer <[email protected]> AuthorDate: Mon Jan 5 14:50:51 2026 +0000 Change how RAT checks are applied --- atr/archives.py | 31 ++- atr/log.py | 4 +- atr/tasks/checks/__init__.py | 4 + atr/tasks/checks/rat.py | 296 ++++++++++++++------- .../557F8D855DEF8BBE2DC5603B64C271BB87B7FE7B.asc | 42 +++ .../68FF2E20F02B070D73D416188DE8CC167FE2663A.asc | 42 --- playwright/apache-test-0.2/apache-test-0.2.tar.gz | Bin 4391 -> 4400 bytes .../apache-test-0.2/apache-test-0.2.tar.gz.asc | 10 +- .../apache-test-0.2/apache-test-0.2.tar.gz.sha512 | 2 +- playwright/mk.sh | 2 +- 10 files changed, 274 insertions(+), 159 deletions(-) diff --git a/atr/archives.py b/atr/archives.py index b3bcbf4..2560c95 100644 --- a/atr/archives.py +++ b/atr/archives.py @@ -82,7 +82,7 @@ def total_size(tgz_path: str, chunk_size: int = 4096) -> int: return total_size -def _archive_extract_member( +def _archive_extract_member( # noqa: C901 tf: tarfile.TarFile, member: tarfile.TarInfo, extract_dir: str, @@ -101,8 +101,10 @@ def _archive_extract_member( if member.isdev(): return 0, extracted_paths + # Only track files that pass the path safety check if track_files and isinstance(track_files, set) and (member_basename in track_files): - extracted_paths.append(member.name) + if _safe_path(extract_dir, member.name) is not None: + extracted_paths.append(member.name) # Check whether extraction would exceed the size limit if member.isreg() and ((total_extracted + member.size) > max_size): @@ -114,8 +116,7 @@ def _archive_extract_member( # Extract directories directly if member.isdir(): # Ensure the path is safe before extracting - target_path = os.path.join(extract_dir, member.name) - if not os.path.abspath(target_path).startswith(os.path.abspath(extract_dir)): + if _safe_path(extract_dir, member.name) is None: log.warning(f"Skipping potentially unsafe path: {member.name}") return 0, extracted_paths tf.extract(member, extract_dir, numeric_owner=True) @@ -144,8 +145,8 @@ def _archive_extract_safe_process_file( chunk_size: int, ) -> int: """Process a single file member during safe archive extraction.""" - target_path = os.path.join(extract_dir, member.name) - if not os.path.abspath(target_path).startswith(os.path.abspath(extract_dir)): + target_path = _safe_path(extract_dir, member.name) + if target_path is None: log.warning(f"Skipping potentially unsafe path: {member.name}") return 0 @@ -235,7 +236,8 @@ def _archive_extract_safe_process_symlink(member: tarfile.TarInfo, extract_dir: def _safe_path(base_dir: str, *paths: str) -> str | None: """Return an absolute path within the base_dir built from the given paths, or None if it escapes.""" target = os.path.abspath(os.path.join(base_dir, *paths)) - if target.startswith(os.path.abspath(base_dir)): + abs_base = os.path.abspath(base_dir) + if (target == abs_base) or target.startswith(abs_base + os.sep): return target return None @@ -277,8 +279,11 @@ def _zip_archive_extract_member( extracted_paths: list[str] = [], ) -> tuple[int, list[str]]: member_basename = os.path.basename(member.name) - if track_files and (isinstance(track_files, set) and (member_basename in track_files)): - extracted_paths.append(member.name) + + # Only track files that pass the path safety check + if track_files and isinstance(track_files, set) and (member_basename in track_files): + if _safe_path(extract_dir, member.name) is not None: + extracted_paths.append(member.name) if member_basename.startswith("._"): return 0, extracted_paths @@ -290,8 +295,8 @@ def _zip_archive_extract_member( ) if member.isdir(): - target_path = os.path.join(extract_dir, member.name) - if not os.path.abspath(target_path).startswith(os.path.abspath(extract_dir)): + target_path = _safe_path(extract_dir, member.name) + if target_path is None: log.warning(f"Skipping potentially unsafe path: {member.name}") return 0, extracted_paths os.makedirs(target_path, exist_ok=True) @@ -314,8 +319,8 @@ def _zip_extract_safe_process_file( max_size: int, chunk_size: int, ) -> int: - target_path = os.path.join(extract_dir, member.name) - if not os.path.abspath(target_path).startswith(os.path.abspath(extract_dir)): + target_path = _safe_path(extract_dir, member.name) + if target_path is None: log.warning(f"Skipping potentially unsafe path: {member.name}") return 0 diff --git a/atr/log.py b/atr/log.py index b138c8c..e121c20 100644 --- a/atr/log.py +++ b/atr/log.py @@ -29,7 +29,7 @@ _global_recent_logs: collections.deque[str] | None = None _global_recent_logs_lock = threading.Lock() -class _BufferingHandler(logging.Handler): +class BufferingHandler(logging.Handler): def emit(self, record: logging.LogRecord) -> None: if _global_recent_logs is None: return @@ -104,7 +104,7 @@ def info(msg: str) -> None: def create_debug_handler() -> logging.Handler: global _global_recent_logs _global_recent_logs = collections.deque(maxlen=100) - handler = _BufferingHandler() + handler = BufferingHandler() handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s")) handler.setLevel(logging.DEBUG) return handler diff --git a/atr/tasks/checks/__init__.py b/atr/tasks/checks/__init__.py index 09a15d3..6bcfb36 100644 --- a/atr/tasks/checks/__init__.py +++ b/atr/tasks/checks/__init__.py @@ -204,6 +204,10 @@ class Recorder: if not await aiofiles.os.path.isfile(path): return False + no_cache_file = self.abs_path_base() / ".atr-no-cache" + if await aiofiles.os.path.exists(no_cache_file): + return False + self.__input_hash = await _compute_file_hash(path) async with db.session() as data: diff --git a/atr/tasks/checks/rat.py b/atr/tasks/checks/rat.py index 65840c8..0ca3d04 100644 --- a/atr/tasks/checks/rat.py +++ b/atr/tasks/checks/rat.py @@ -42,7 +42,35 @@ _JAVA_MEMORY_ARGS: Final[list[str]] = [] # "-XX:MaxRAM=256m", # "-XX:CompressedClassSpaceSize=16m" # ] -_RAT_EXCLUDES_FILENAMES: Final[set[str]] = {".rat-excludes", "rat-excludes.txt"} + +# Generated file patterns, always excluded +_GENERATED_FILE_PATTERNS: Final[list[str]] = [ + "**/*.bundle.js", + "**/*.chunk.js", + "**/*.css.map", + "**/*.js.map", + "**/*.min.css", + "**/*.min.js", + "**/*.min.map", +] + +# The name of the file that contains the exclusions for the specified archive +_RAT_EXCLUDES_FILENAME: Final[str] = ".rat-excludes" + +# The name of the RAT report file +_RAT_REPORT_FILENAME: Final[str] = "rat-report.xml" + +# Standard exclusions, always applied explicitly +_STD_EXCLUSIONS_ALWAYS: Final[list[str]] = ["MISC", "HIDDEN_DIR", "MAC"] + +# Additional exclusions when no project exclusion file is found +_STD_EXCLUSIONS_EXTENDED: Final[list[str]] = [ + "MAVEN", + "ECLIPSE", + "IDEA", + "GIT", + "STANDARD_SCMS", +] async def check(args: checks.FunctionArguments) -> results.Results | None: @@ -74,6 +102,50 @@ async def check(args: checks.FunctionArguments) -> results.Results | None: return None +def _build_rat_command( + rat_jar_path: str, + xml_output_path: str, + exclude_file: str | None, +) -> list[str]: + """Build the RAT command with appropriate exclusions.""" + command = [ + "java", + *_JAVA_MEMORY_ARGS, + "-jar", + rat_jar_path, + "--output-style", + "xml", + "--output-file", + xml_output_path, + "--counter-max", + "UNAPPROVED:-1", + "--counter-min", + "LICENSE_CATEGORIES:0", + "LICENSE_NAMES:0", + "STANDARDS:0", + ] + + for std in _STD_EXCLUSIONS_ALWAYS: + command.extend(["--input-exclude-std", std]) + + if exclude_file is None: + for std in _STD_EXCLUSIONS_EXTENDED: + command.extend(["--input-exclude-std", std]) + + for pattern in _GENERATED_FILE_PATTERNS: + command.extend(["--input-exclude", pattern]) + + command.extend(["--input-exclude", _RAT_REPORT_FILENAME]) + + if exclude_file is not None: + command.extend(["--input-exclude", _RAT_EXCLUDES_FILENAME]) + command.extend(["--input-exclude-file", exclude_file]) + + command.extend(["--", "."]) + + return command + + async def _check_core( args: checks.FunctionArguments, recorder: checks.Recorder, artifact_abs_path: pathlib.Path ) -> None: @@ -120,7 +192,7 @@ async def _check_core( await recorder.success(result_data["message"], result_data) -def _check_core_logic( +def _check_core_logic( # noqa: C901 artifact_path: str, rat_jar_path: str = _CONFIG.APACHE_RAT_JAR_PATH, max_extract_size: int = _CONFIG.MAX_EXTRACT_SIZE, @@ -168,29 +240,79 @@ def _check_core_logic( # Extract the archive to the temporary directory log.info(f"Extracting {artifact_path} to {temp_dir}") - extracted_size, extracted_paths = archives.extract( + extracted_size, exclude_file_paths = archives.extract( artifact_path, temp_dir, max_size=max_extract_size, chunk_size=chunk_size, - track_files=_RAT_EXCLUDES_FILENAMES, + track_files={_RAT_EXCLUDES_FILENAME}, ) log.info(f"Extracted {extracted_size} bytes") + log.info(f"Found {len(exclude_file_paths)} {_RAT_EXCLUDES_FILENAME} file(s): {exclude_file_paths}") - # Find the root directory - if (extract_dir := _extracted_dir(temp_dir)) is None: - log.error("No root directory found in archive") + # Validate that we found at most one exclusion file + if len(exclude_file_paths) > 1: + log.error(f"Multiple {_RAT_EXCLUDES_FILENAME} files found: {exclude_file_paths}") return { "valid": False, - "message": "No root directory found in archive", - "errors": [], + "message": f"Multiple {_RAT_EXCLUDES_FILENAME} files not allowed (found {len(exclude_file_paths)})", + "total_files": 0, + "approved_licenses": 0, + "unapproved_licenses": 0, + "unknown_licenses": 0, + "unapproved_files": [], + "unknown_license_files": [], + "errors": [f"Found {len(exclude_file_paths)} {_RAT_EXCLUDES_FILENAME} files"], } - log.info(f"Using root directory: {extract_dir}") + # Narrow to single path after validation + exclude_file_path: str | None = exclude_file_paths[0] if exclude_file_paths else None + + # Determine scan root + if exclude_file_path is not None: + scan_root = os.path.dirname(os.path.join(temp_dir, exclude_file_path)) + + # Verify that scan_root is inside temp_dir + abs_scan_root = os.path.abspath(scan_root) + abs_temp_dir = os.path.abspath(temp_dir) + scan_root_is_inside = (abs_scan_root == abs_temp_dir) or abs_scan_root.startswith(abs_temp_dir + os.sep) + if not scan_root_is_inside: + log.error(f"Scan root {scan_root} is outside temp_dir {temp_dir}") + return { + "valid": False, + "message": "Invalid archive structure: exclusion file path escapes extraction directory", + "total_files": 0, + "approved_licenses": 0, + "unapproved_licenses": 0, + "unknown_licenses": 0, + "unapproved_files": [], + "unknown_license_files": [], + "errors": ["Exclusion file path escapes extraction directory"], + } + + log.info(f"Using {_RAT_EXCLUDES_FILENAME} directory as scan root: {scan_root}") + + untracked_count = _count_files_outside_directory(temp_dir, scan_root) + if untracked_count > 0: + log.error(f"Found {untracked_count} file(s) outside {_RAT_EXCLUDES_FILENAME} directory") + return { + "valid": False, + "message": f"Files exist outside {_RAT_EXCLUDES_FILENAME} directory ({untracked_count} found)", + "total_files": 0, + "approved_licenses": 0, + "unapproved_licenses": 0, + "unknown_licenses": 0, + "unapproved_files": [], + "unknown_license_files": [], + "errors": [f"{untracked_count} file(s) outside {_RAT_EXCLUDES_FILENAME} directory"], + } + else: + scan_root = temp_dir + log.info(f"No {_RAT_EXCLUDES_FILENAME} found, using temp_dir as scan root: {scan_root}") # Execute RAT and get results or error error_result, xml_output_path = _check_core_logic_execute_rat( - rat_jar_path, extract_dir, temp_dir, extracted_paths + rat_jar_path, scan_root, temp_dir, exclude_file_path ) if error_result: return error_result @@ -201,18 +323,24 @@ def _check_core_logic( if xml_output_path is None: raise ValueError("XML output path is None") - results = _check_core_logic_parse_output(xml_output_path, extract_dir) + results = _check_core_logic_parse_output(xml_output_path, scan_root) log.info(f"Successfully parsed RAT output with {util.plural(results.get('total_files', 0), 'file')}") - # The unknown_license_files key may contain a list of dicts + # The unknown_license_files and unapproved_files keys contain lists of dicts # {"name": "./README.md", "license": "Unknown license"} - # The path is missing the root of the archive, so we add it - extract_dir_basename = os.path.basename(extract_dir) - for file in results["unknown_license_files"]: - file["name"] = os.path.join( - extract_dir_basename, - os.path.normpath(file["name"]), - ) + # The path is relative to scan_root, so we prepend the scan_root relative path + scan_root_rel = os.path.relpath(scan_root, temp_dir) + if scan_root_rel != ".": + for file in results["unknown_license_files"]: + file["name"] = os.path.join( + scan_root_rel, + os.path.normpath(file["name"]), + ) + for file in results["unapproved_files"]: + file["name"] = os.path.join( + scan_root_rel, + os.path.normpath(file["name"]), + ) return results @@ -234,42 +362,37 @@ def _check_core_logic( def _check_core_logic_execute_rat( - rat_jar_path: str, extract_dir: str, temp_dir: str, excluded_paths: list[str] + rat_jar_path: str, scan_root: str, temp_dir: str, exclude_file_path: str | None ) -> tuple[dict[str, Any] | None, str | None]: """Execute Apache RAT and process its output.""" - # Define output file path - xml_output_path = os.path.join(temp_dir, "rat-report.xml") + xml_output_path = os.path.join(temp_dir, _RAT_REPORT_FILENAME) log.info(f"XML output will be written to: {xml_output_path}") - # Run Apache RAT on the extracted directory - # TODO: From RAT 0.17, --exclude will become --input-exclude - # TODO: Check whether --exclude NAME works on inner files - # (Note that we presently use _rat_apply_exclusions to apply exclusions instead) - command = [ - "java", - *_JAVA_MEMORY_ARGS, - "-jar", - rat_jar_path, - "--output-style", - "xml", - "--output-file", - xml_output_path, - "--counter-max", - "UNAPPROVED:-1", - "--counter-min", - "LICENSE_CATEGORIES:0", - "LICENSE_NAMES:0", - "STANDARDS:0", - "--", - ".", - ] - if excluded_paths: - _rat_apply_exclusions(extract_dir, excluded_paths, temp_dir) + # Convert exclusion file path from temp_dir relative to scan_root relative + exclude_file: str | None = None + if exclude_file_path is not None: + abs_path = os.path.join(temp_dir, exclude_file_path) + if not (os.path.exists(abs_path) and os.path.isfile(abs_path)): + log.error(f"Exclusion file not found or not a regular file: {abs_path}") + return { + "valid": False, + "message": f"Exclusion file is not a regular file: {exclude_file_path}", + "total_files": 0, + "approved_licenses": 0, + "unapproved_licenses": 0, + "unknown_licenses": 0, + "unapproved_files": [], + "unknown_license_files": [], + "errors": [f"Expected exclusion file but found: {abs_path}"], + }, None + exclude_file = os.path.relpath(abs_path, scan_root) + log.info(f"Using exclusion file: {exclude_file}") + command = _build_rat_command(rat_jar_path, xml_output_path, exclude_file) log.info(f"Running Apache RAT: {' '.join(command)}") - # Change working directory to extract_dir when running the process + # Change working directory to scan_root when running the process current_dir = os.getcwd() - os.chdir(extract_dir) + os.chdir(scan_root) log.info(f"Executing Apache RAT from directory: {os.getcwd()}") @@ -549,53 +672,36 @@ def _check_java_installed() -> dict[str, Any] | None: } -def _extracted_dir(temp_dir: str) -> str | None: - # Loop through all the dirs in temp_dir - extract_dir = None - log.info(f"Checking directories in {temp_dir}: {os.listdir(temp_dir)}") - for dir_name in os.listdir(temp_dir): - if dir_name.startswith("."): - continue - dir_path = os.path.join(temp_dir, dir_name) - if not os.path.isdir(dir_path): - raise ValueError(f"Unknown file type found in temporary directory: {dir_path}") - if extract_dir is None: - extract_dir = dir_path - else: - raise ValueError(f"Multiple root directories found: {extract_dir}, {dir_path}") - return extract_dir - - -def _rat_apply_exclusions(extract_dir: str, excluded_paths: list[str], temp_dir: str) -> None: - """Apply exclusions to the extracted directory.""" - # Exclusions are difficult using the command line version of RAT - # Each line is interpreted as a literal AND a glob AND a regex - # Then, if ANY of those three match a filename, the file is excluded - # You cannot specify which syntax to use; all three are always tried - # You cannot specify that you want to match against the whole path - # Therefore, we take a different approach - # We interpret the exclusion file as a glob file in .gitignore format - # Then, we simply remove any files that match the glob - exclusion_lines = [] - for excluded_path in excluded_paths: - abs_excluded_path = os.path.join(temp_dir, excluded_path) - if not os.path.exists(abs_excluded_path): - log.error(f"Exclusion file not found: {abs_excluded_path}") - continue - if not os.path.isfile(abs_excluded_path): - log.error(f"Exclusion file is not a file: {abs_excluded_path}") +def _count_files_outside_directory(temp_dir: str, scan_root: str) -> int: + """Count regular files that exist outside the scan_root directory.""" + count = 0 + scan_root_rel = os.path.relpath(scan_root, temp_dir) + if scan_root_rel == ".": + scan_root_rel = "" + + for root, _dirs, files in os.walk(temp_dir): + rel_root = os.path.relpath(root, temp_dir) + if rel_root == ".": + rel_root = "" + + if _is_inside_directory(rel_root, scan_root_rel): continue - with open(abs_excluded_path, encoding="utf-8") as f: - exclusion_lines.extend(f.readlines()) - matcher = util.create_path_matcher( - exclusion_lines, pathlib.Path(extract_dir) / ".ignore", pathlib.Path(extract_dir) - ) - for root, _dirs, files in os.walk(extract_dir): - for file in files: - abs_path = os.path.join(root, file) - if matcher(abs_path): - log.info(f"Removing {abs_path} because it matches the exclusion") - os.remove(abs_path) + + # for filename in files: + # if not filename.startswith("."): + # count += 1 + count += len(files) + + return count + + +def _is_inside_directory(path: str, directory: str) -> bool: + """Check whether path is inside directory, or is the directory itself.""" + if directory == "": + return True + if path == directory: + return True + return path.startswith(directory + os.sep) def _summary_message(valid: bool, unapproved_licenses: int, unknown_licenses: int) -> str: diff --git a/playwright/557F8D855DEF8BBE2DC5603B64C271BB87B7FE7B.asc b/playwright/557F8D855DEF8BBE2DC5603B64C271BB87B7FE7B.asc new file mode 100644 index 0000000..33cb964 --- /dev/null +++ b/playwright/557F8D855DEF8BBE2DC5603B64C271BB87B7FE7B.asc @@ -0,0 +1,42 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: 557F 8D85 5DEF 8BBE 2DC5 603B 64C2 71BB 87B7 FE7B +Comment: Apache Tooling (For test use only) <apache-tooling@exam + +xjMEaVvlZBYJKwYBBAHaRw8BAQdAZdQYnph1gHloUcpR2mZzwhL6k0HT+QDBqM/H +vyjZzyvCwBEEHxYKAIMFgmlb5WQFiQWkj70DCwkHCRBkwnG7h7f+e0cUAAAAAAAe +ACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmdoq3iHXnuFOOLJfwpeu4XT +VX4msduw7YD3giI9Lf+dygMVCggCm4ECHgkWIQRVf42FXe+Lvi3FYDtkwnG7h7f+ +ewAAplMA+gNORg2Xc8WGcltomGH3KM+9scvjELz4R2ybQ+AcSBU9AP0fPXYWetgU +A7DWRJoM8xL2qwbcX/yTTWEOEhnm374dDs1DQXBhY2hlIFRvb2xpbmcgKEZvciB0 +ZXN0IHVzZSBvbmx5KSA8YXBhY2hlLXRvb2xpbmdAZXhhbXBsZS5pbnZhbGlkPsLA +FAQTFgoAhgWCaVvlZAWJBaSPvQMLCQcJEGTCcbuHt/57RxQAAAAAAB4AIHNhbHRA +bm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZ13YdB0XL3hrUouaLDHSmDSR+u2RUONT +MnA9JMbpu7G3AxUKCAKZAQKbgQIeCRYhBFV/jYVd74u+LcVgO2TCcbuHt/57AADX +/wEAnV7b6coWlYX5qacWs3RZndBpIik0/7EfXolzOlE6mtsBAKwTWtHuo4H/qDLm +Gz61bJpTEnjtJIMJ+QgXMpj+QfsJzjMEaVvlZBYJKwYBBAHaRw8BAQdAI94zBjdn +L+Q8MpAY9HplBoYrVxd1Zf3dnw4LPFMmOirCwMUEGBYKATcFgmlb5WQFiQWkj70J +EGTCcbuHt/57RxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9y +Z575eSorjzm2UstnDzHuJdkdDGp5HdUpz5RPmyeQj/CmApuCvqAEGRYKAG8Fgmlb +5WQJEKH1+F2brqYSRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdw +Lm9yZ0NOwQpHaiAxRI4QJN8XOHCqPSMENuyzuBiSzIKlZMf9FiEElA9rZFYELdlZ +UocIofX4XZuuphIAAH7UAQCsOQplKWu2kExRj47mCt+vOaBUfQa9OJJHi88wViq3 +lQD/VkgsQ0EphsWq/a28d0Qy86DGbY9FcWOnBFQVah/KRwAWIQRVf42FXe+Lvi3F +YDtkwnG7h7f+ewAAaFQA/0j09N78B9/kSMs9Fb27KPyExjKWKigr15tzYFJlaqPg +AQDYH3DAnIb5fpD2zB6kJ7a3ylrK3mHunThrNjc4W4nLDM4zBGlb5WQWCSsGAQQB +2kcPAQEHQFy/vRPUG0EwCmqNrInUI8x3yCtc+R1kvnrE9IBNc+eLwsDFBBgWCgE3 +BYJpW+VkBYkFpI+9CRBkwnG7h7f+e0cUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5z +ZXF1b2lhLXBncC5vcmcY5GkzClw4T3+kUaErDbI8EKTVhdQZ5Rf1ZPfQpmWp6AKb +oL6gBBkWCgBvBYJpW+VkCRCP1wFtWCy38UcUAAAAAAAeACBzYWx0QG5vdGF0aW9u +cy5zZXF1b2lhLXBncC5vcmdMQVQtulNNFpGLEZa1iM0kt+/upQJkVMp4ZDNOuBi6 +JxYhBFOyL2Xlm8KYWYThIY/XAW1YLLfxAAAyNgD9Giw5EGHsqbiG6Goj0lyu2U8u +1+iMVHsZS5J0yLBGJt4A/1tfLkVXT6Ee9WkJFUu+SSjEKpiWVWXcI3TAJsP+Bj4H +FiEEVX+NhV3vi74txWA7ZMJxu4e3/nsAAAF4AQC7HS6gLQ2T29EnVrUkAtPIeK2x +vvdWtVoWXRK5PgZyzQD8DeoeQ3y6NHFzBzqSxn8QrBtmBxBxUb4jnznC8xmZ3gvO +OARpW+VkEgorBgEEAZdVAQUBAQdAeFiwmTrBMhU3LWr8jQUmshetnbIU7VXHIlor +b/tHBmIDAQgHwsAGBBgWCgB4BYJpW+VkBYkFpI+9CRBkwnG7h7f+e0cUAAAAAAAe +ACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmcMAYQv3Yk8H3qHGsKaG7b9 +AKme/nZ4eChCkwGM7mb+TQKbjBYhBFV/jYVd74u+LcVgO2TCcbuHt/57AACPIgD7 +BNP+DIaSxDSj11rom16KN16bZ3/lWUMAOplGHOWbAa0A/jyf1xOvZMVqvJPo+42a +9Pse1pGqyUGyeT6owz7abyEJ +=XQ9q +-----END PGP PUBLIC KEY BLOCK----- diff --git a/playwright/68FF2E20F02B070D73D416188DE8CC167FE2663A.asc b/playwright/68FF2E20F02B070D73D416188DE8CC167FE2663A.asc deleted file mode 100644 index 942dfef..0000000 --- a/playwright/68FF2E20F02B070D73D416188DE8CC167FE2663A.asc +++ /dev/null @@ -1,42 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Comment: 68FF 2E20 F02B 070D 73D4 1618 8DE8 CC16 7FE2 663A -Comment: Apache Tooling (For test use only) <apache-tooling@exam - -xjMEaO1PsBYJKwYBBAHaRw8BAQdApoMTlP31+p4iNHPXRsluuFJD7/n7ZfvbXTaW -nuPqcNXCwBEEHxYKAIMFgmjtT7AFiQWkj70DCwkHCRCN6MwWf+JmOkcUAAAAAAAe -ACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmc62pYvwVHI/mS0pKwOQyF2 -4zTbGfhRAUmA5Lb0wiCA8wMVCggCm4ECHgkWIQRo/y4g8CsHDXPUFhiN6MwWf+Jm -OgAAaCsA/juShbk2IlhDKf2KxwTMr88Ce/zDsw4+eiWtrthgBUeTAP4grngx+xez -Ih3T0oHijFiRRFHeCrKtrD7qUYiRWZQrDc1DQXBhY2hlIFRvb2xpbmcgKEZvciB0 -ZXN0IHVzZSBvbmx5KSA8YXBhY2hlLXRvb2xpbmdAZXhhbXBsZS5pbnZhbGlkPsLA -FAQTFgoAhgWCaO1PsAWJBaSPvQMLCQcJEI3ozBZ/4mY6RxQAAAAAAB4AIHNhbHRA -bm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZy/CVowGIUPB/Q2pB93lBODdG76rdB57 -tRtDUd1vvJTbAxUKCAKZAQKbgQIeCRYhBGj/LiDwKwcNc9QWGI3ozBZ/4mY6AAC2 -ggD/RzmgDOdwDbYa3yunGlaeNdXX9mKZr6l1ZZxPgxjCUUgA/iv14Q0jdlQTlnCE -mU2KerEx3u4DKxTL3vSzrt7/YfYFzjMEaO1PsBYJKwYBBAHaRw8BAQdAOj8uLbY9 -uV5X5dHQouxpqNmBEiVL3yULoRGZIIcyjgzCwMUEGBYKATcFgmjtT7AFiQWkj70J -EI3ozBZ/4mY6RxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9y -Z/rQQDjxu84TK0fnjT6/eJfY7Ry9NZPUC4OnZ22u3H2eApugvqAEGRYKAG8Fgmjt -T7AJEB4aFkanXZJrRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdw -Lm9yZ3usYbMZaif3OJ191geiqbHhOJKxQAnKeYrTTRIBRtuSFiEEHnCR6AIvyq8N -clBVHhoWRqddkmsAANfnAP9q5S4wzYCzBWXBMgT8GkGQ6qlozPKbDrLlSBByuPWx -1AD/bQxhQOSOyoTl93gX+LEgzOl90eilDC36YcwlAAvPSQcWIQRo/y4g8CsHDXPU -FhiN6MwWf+JmOgAAf1MBAM6fEH6DqxAej4v5JMSvhFK/VSMy9l74KEjdS4zQqGf+ -AP0b2hno+V/sKwsIZeLcT2WW8ymesnwcMlyJAKRawsGODs4zBGjtT7AWCSsGAQQB -2kcPAQEHQOnskJXKy8myDOIN96kyCybjuusSj0UMKKOcKpKgCbjBwsDFBBgWCgE3 -BYJo7U+wBYkFpI+9CRCN6MwWf+JmOkcUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5z -ZXF1b2lhLXBncC5vcmetuP08aKM3bgGpJSqcY0BFDIgHZVRzbhqkS6jW70k5rgKb -gr6gBBkWCgBvBYJo7U+wCRCBsaC42dIMukcUAAAAAAAeACBzYWx0QG5vdGF0aW9u -cy5zZXF1b2lhLXBncC5vcmdvv5LhZuUYSxJ371orAeZNemqPQFs2TVnNAkqcOvQl -xhYhBKMvD8z/SMlPuXH5hYGxoLjZ0gy6AABPrQEA/68vHpMtFSLciL11wPdwlQya -7IgXmd+1ex/fKd0lL8UBAKs6o8npS3TFMOdQ/lY77+2i4mQ8R/06LG7UqJlRA9YF -FiEEaP8uIPArBw1z1BYYjejMFn/iZjoAAILfAQCTsMRBr0p26+mM9DyAfloTXjtC -b64WedgkrliFylIEswEAhgoBH5hKugQuQoGGMAaCgfiQiDjzKmy5Qq5apdqdzgjO -OARo7U+wEgorBgEEAZdVAQUBAQdA2SplsmuOmaNAaFJv5/6ZIU4fo2/tAhtiB4mZ -IwtSkWoDAQgHwsAGBBgWCgB4BYJo7U+wBYkFpI+9CRCN6MwWf+JmOkcUAAAAAAAe -ACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmdlwwnRv1QM8Bh2keRKFRz4 -8KCfPtinCmGR/RXxuR3A+wKbjBYhBGj/LiDwKwcNc9QWGI3ozBZ/4mY6AABx9QEA -rTRZ8U7JxlVC/iX8fMzPNC3Ynmh6cH9feo7IP/DBVmAA/AmpD4UbPIrViv9jCHIN -EQUjXZv3x5ZYr8Fx4ic4ldgF -=eVnv ------END PGP PUBLIC KEY BLOCK----- diff --git a/playwright/apache-test-0.2/apache-test-0.2.tar.gz b/playwright/apache-test-0.2/apache-test-0.2.tar.gz index cdf2aa6..0ff4a49 100644 Binary files a/playwright/apache-test-0.2/apache-test-0.2.tar.gz and b/playwright/apache-test-0.2/apache-test-0.2.tar.gz differ diff --git a/playwright/apache-test-0.2/apache-test-0.2.tar.gz.asc b/playwright/apache-test-0.2/apache-test-0.2.tar.gz.asc index ee315f7..2c985d5 100644 --- a/playwright/apache-test-0.2/apache-test-0.2.tar.gz.asc +++ b/playwright/apache-test-0.2/apache-test-0.2.tar.gz.asc @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNATURE----- -wr0EABYKAG8FgmjtT7AJEIGxoLjZ0gy6RxQAAAAAAB4AIHNhbHRAbm90YXRpb25z -LnNlcXVvaWEtcGdwLm9yZ4VkofDuJJfmgWXBNbtwfchEvmhkIDXiWM6KftpKJ6HY -FiEEoy8PzP9IyU+5cfmFgbGguNnSDLoAAGw/AQDAk4F3V56S1Rtrirm/ACTN59wu -L4OohdalGj+tXF45mwD+OssTPHA5li7U6oDv3Aj3zXtCD6zWqfumaW0ePCxzOQs= -=QK4u +wr0EABYKAG8Fgmlb5WQJEKH1+F2brqYSRxQAAAAAAB4AIHNhbHRAbm90YXRpb25z +LnNlcXVvaWEtcGdwLm9yZz5EQzdcny9mjUUxatFEOaClOjI9cNqJoF1OJDQx7uAa +FiEElA9rZFYELdlZUocIofX4XZuuphIAADBzAQDECUPchT+jiheztMxLxy9hJYkL +M9eBBQI3WII8MK8yVAEAyRajfs9qExqT1d9Jh2LsQfO6wXAPpca6AUaGIlrhngo= +=ybPh -----END PGP SIGNATURE----- diff --git a/playwright/apache-test-0.2/apache-test-0.2.tar.gz.sha512 b/playwright/apache-test-0.2/apache-test-0.2.tar.gz.sha512 index bc07ae9..9793b62 100644 --- a/playwright/apache-test-0.2/apache-test-0.2.tar.gz.sha512 +++ b/playwright/apache-test-0.2/apache-test-0.2.tar.gz.sha512 @@ -1 +1 @@ -c6268245288e458795dbbc30b254493df29ce0829d770e0e22002cdb74043ef79e98436e7a1e67371974288cd13964a99538047ef53a4e4659075af283ee7c50 apache-test-0.2.tar.gz +e7baa0331839acdd4e185ddf20c017dcc5eda97c2ca42471c7ba8a722fa9c7164ccf0fd9cffcc35ae48d8d4e9966be4a7064458d8dbfc30f1ccf6856ca189caa apache-test-0.2.tar.gz diff --git a/playwright/mk.sh b/playwright/mk.sh index 8fbc956..0354319 100755 --- a/playwright/mk.sh +++ b/playwright/mk.sh @@ -29,7 +29,7 @@ sq key delete --cert-file "${_fp}.secret.asc" --output "${_fp}.asc" # Enter the directory containing the artifact cd apache-test-0.2/ -rm ./*.asc ./*.sha512 +rm -f ./*.asc ./*.sha512 # Generate the SHA-2-512 hash sha512sum apache-test-0.2.tar.gz > \ --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
