From b4dee062ec3b0f7a6eaaf04bbaac2e4b50b418c1 Mon Sep 17 00:00:00 2001 From: Joost van Zwieten Date: Fri, 2 Sep 2022 12:48:10 +0200 Subject: [PATCH] container image: support building specified wheel --- .github/workflows/test.yaml | 3 ++- devtools/container/build.py | 53 ++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f9a6f1ecc..228dc0c1d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -162,6 +162,7 @@ jobs: env: # Fixes https://github.com/actions/virtual-environments/issues/3080 STORAGE_OPTS: overlay.mount_program=/usr/bin/fuse-overlayfs + _wheel: ${{ needs.build-python-package.outputs.wheel }} steps: - name: Checkout uses: actions/checkout@v2 @@ -182,7 +183,7 @@ jobs: env: _base: ${{ env.official_container_repository }}:${{ steps.tags.outputs.base }} _name: ${{ env.official_container_repository }}:${{ steps.tags.outputs.image }} - run: python3 -um devtools.container.build --build-from-worktree --name "$_name" --base "$_base" + run: python3 -um devtools.container.build --revision "$GITHUB_SHA" --wheel "$_wheel" --examples examples --name "$_name" --base "$_base" - name: Test examples/laplace.py env: _image: ${{ steps.build.outputs.id }} diff --git a/devtools/container/build.py b/devtools/container/build.py index 6e13b447c..e56e93ee2 100644 --- a/devtools/container/build.py +++ b/devtools/container/build.py @@ -14,19 +14,19 @@ parser.add_argument('--base', required=True, help='the base image to build upon; example: `docker.io/evalf/nutils` or `docker.io/evalf/nutils:_base_latest`') parser.add_argument('--name', metavar='NAME', help='the name to attach to the image; defaults to `{OFFICIAL_CONTAINER_REPO}:TAG` where TAG is based on REV') parser.add_argument('--revision', '--rev', metavar='REV', help='set image label `org.opencontainers.image.revision` to the commit hash refered to by REV') -parser.add_argument('--build-from-worktree', action='store_const', const=True, default=False, help='build from the worktree') +parser.add_argument('--wheel', help='use the given Nutils wheel; if absent, a wheel will be build for the given revision') +parser.add_argument('--examples', help='include the given examples directory; if absent, the examples from the given revision will be included') args = parser.parse_args() -if not args.build_from_worktree and not args.revision: - raise SystemExit('either `--revision` or `--build-from-worktree` must be specified') +if not args.wheel and not args.revision: + raise SystemExit('either `--revision` or `--wheel` must be specified') +if not args.examples and not args.revision: + raise SystemExit('either `--examples` or `--wheel` must be specified') rev = args.revision or 'HEAD' git = Git() commit = git.get_commit_from_rev(rev) -if args.build_from_worktree and args.revision and (head_commit := git.get_commit_from_rev('HEAD')) != commit: - raise SystemExit(f'`HEAD` points to `{head_commit}` but `--revision={args.revision}` points to `{commit}`') - if args.name and ':' in args.name: image_name = args.name tag = image_name.rsplit(':', 1)[-1] @@ -40,30 +40,33 @@ with ExitStack() as stack: - if args.build_from_worktree: - dist = Path()/'dist' - examples = Path()/'examples' - log.info(f'installing Nutils from {dist}') - log.info(f'using examples from {examples}') - else: - # Check out Nutils in a clean working tree, build a wheel and use the working tree as `src`. - log.info(f'using examples from commit {commit}') + if not args.wheel or not args.examples: src = stack.enter_context(git.worktree(typing.cast(str, commit))) - log.info(f'building wheel from commit {commit}') + + if args.wheel: + wheel = Path(args.wheel) + if not wheel.exists(): + log.error(f'wheel does not exist: {wheel}') + raise SystemExit(1) + log.info(f'installing Nutils from {wheel}') + else: + log.info(f'building wheel for commit {commit}') run(sys.executable, 'setup.py', 'bdist_wheel', cwd=str(src.path), env=dict(SOURCE_DATE_EPOCH=str(src.get_commit_timestamp('HEAD')))) - dist = src.path/'dist' - examples = src.path/'examples' + wheel, = (src.path / 'dist').glob('nutils-*.whl') - dist = Path(dist) - if not dist.exists(): - raise SystemExit(f'cannot find dist dir: {dist}') - examples = Path(examples) - if not examples.exists(): - raise SystemExit(f'cannot find example dir: {examples}') + if args.examples: + examples = Path(args.examples) + if not examples.exists(): + log.error(f'examples directory does not exist: {examples}') + raise SystemExit(1) + log.info(f'using examples from {examples}') + else: + examples = src.path / 'examples' + log.info(f'using examples from commit {commit}') - container = stack.enter_context(Container.new_from(base, mounts=[Mount(src=dist, dst='/mnt')])) + container = stack.enter_context(Container.new_from(base, mounts=[Mount(src=wheel, dst=f'/{wheel.name}')])) - container.run('pip', 'install', '--no-cache-dir', '--no-index', '--find-links', 'file:///mnt/', 'nutils', env=dict(PYTHONHASHSEED='0')) + container.run('pip', 'install', '--no-cache-dir', f'/{wheel.name}[export_mpl,import_gmsh,matrix_scipy]', env=dict(PYTHONHASHSEED='0')) container.run('pip', 'install', '--no-cache-dir', 'https://github.com/evalf/nutils-SI/archive/main.tar.gz', env=dict(PYTHONHASHSEED='0')) container.add_label('org.opencontainers.image.url', 'https://github.com/evalf/nutils') container.add_label('org.opencontainers.image.source', 'https://github.com/evalf/nutils')