From f99cd3082ad8c34ca75c4d4bc4d4e3f0e03d6e96 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Mon, 28 Aug 2023 09:56:13 +0200 Subject: [PATCH] Build Conda packages Add `paths_version` --- .github/workflows/build-all.yml | 50 +++++++++++ .gitignore | 3 +- conda/about.json | 9 ++ conda/build.py | 146 ++++++++++++++++++++++++++++++++ 4 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 conda/about.json create mode 100644 conda/build.py diff --git a/.github/workflows/build-all.yml b/.github/workflows/build-all.yml index 2f3dde80..820df7d8 100644 --- a/.github/workflows/build-all.yml +++ b/.github/workflows/build-all.yml @@ -539,6 +539,56 @@ jobs: env: NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + conda: + name: Build Conda packages + if: github.event.inputs.version + runs-on: ubuntu-latest + needs: + - linux_arm + - linux_arm64 + - linux_x64 + - linux_x86 + - mac_arm64 + - mac_x64 + - win_arm64 + - win_x64 + - win_x86 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Download artifacts + uses: actions/download-artifact@v3 + - name: Create build script + run: | + cat >conda-build.sh < 0, f"Invalid build number {build_number}" + assert source_dir.exists(), f"Source directory {source_dir} does not exist" + assert re.match( + r"^\d+\.\d+\.\d+(?:.\d+)?$", version + ), f"Invalid version {version!r}" + + output_file = output_dir / platform / f"{package}-{version}-{build_number}.tar.bz2" + output_file.parent.mkdir(parents=True, exist_ok=True) + + assert platform in CONDA_PLATFORMS, f"Unknown platform {platform!r}" + operating_system, architecture = CONDA_PLATFORMS[platform] + + files: list[Path] = [] + + with tarfile.open(output_file, "w:bz2") as tar: + for glob in SOURCE_GLOBS: + for file in source_dir.glob(glob): + tar.add(file, file.relative_to(source_dir)) + files.append(file) + assert files, f"No files found for globs {SOURCE_GLOBS}" + + with TemporaryDirectory() as info_dir: + create_json_file( + f"{info_dir}/index.json", + { + "arch": architecture, + "build_number": build_number, + "build": build, + "depends": [], + "name": package, + "platform": operating_system, + "version": version, + }, + ) + + Path(info_dir, "files").write_text( + "\n".join( + str(file.relative_to(source_dir).as_posix()) for file in files + ) + ) + + create_json_file( + f"{info_dir}/paths.json", + { + "paths": [ + { + "_path": str(file.relative_to(source_dir).as_posix()), + "path_type": "hardlink", + "sha256": sha256(file.read_bytes()).hexdigest(), + "size_in_bytes": file.stat().st_size, + } + for file in files + ], + "paths_version": 1, + }, + ) + + if about_file: + assert about_file.exists(), f"About file {about_file} does not exist" + tar.add(about_file, "info/about.json") + + license_file = source_dir / "LICENSE" + if license_file.exists(): + tar.add(license_file, "info/license.txt") + + tar.add(info_dir, "info") + + return output_file + + +def main(): + parser = ArgumentParser(description="Build conda packages.") + parser.add_argument("package", help="Package name") + parser.add_argument("platform", help="Platform") + parser.add_argument("version", help="Version") + parser.add_argument("--source-dir", help="Source directory", type=Path, default=".") + parser.add_argument("--output-dir", help="Output directory", type=Path, default=".") + parser.add_argument("--about-file", help="Path to about.json", type=Path) + parser.add_argument("--build", help="The build string", default="") + parser.add_argument("--build-number", help="The build number", type=int, default=1) + + args = parser.parse_args() + + output_file = conda_build(**vars(args)) + + print(f"Built package {output_file}") + + +if __name__ == "__main__": + main()