2023-11-08 00:15:04 +00:00
|
|
|
# Copyright © 2022, 2023 Vulcanize
|
|
|
|
|
|
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
# Builds webapp containers
|
|
|
|
|
|
|
|
|
|
# env vars:
|
|
|
|
|
# CERC_REPO_BASE_DIR defaults to ~/cerc
|
|
|
|
|
|
2026-01-22 01:58:31 +00:00
|
|
|
# TODO: display the available list of containers;
|
|
|
|
|
# allow re-build of either all or specific containers
|
2023-11-08 00:15:04 +00:00
|
|
|
|
|
|
|
|
import os
|
2024-02-24 03:22:49 +00:00
|
|
|
import sys
|
|
|
|
|
|
2023-11-08 00:15:04 +00:00
|
|
|
from decouple import config
|
|
|
|
|
import click
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from stack_orchestrator.build import build_containers
|
2024-02-28 00:38:11 +00:00
|
|
|
from stack_orchestrator.deploy.webapp.util import determine_base_container, TimedLogger
|
2024-02-23 19:57:47 +00:00
|
|
|
from stack_orchestrator.build.build_types import BuildContext
|
2023-11-08 00:15:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@click.command()
|
2026-01-22 01:58:31 +00:00
|
|
|
@click.option("--base-container")
|
|
|
|
|
@click.option(
|
|
|
|
|
"--source-repo", help="directory containing the webapp to build", required=True
|
|
|
|
|
)
|
|
|
|
|
@click.option(
|
|
|
|
|
"--force-rebuild",
|
|
|
|
|
is_flag=True,
|
|
|
|
|
default=False,
|
|
|
|
|
help="Override dependency checking -- always rebuild",
|
|
|
|
|
)
|
2023-11-08 00:15:04 +00:00
|
|
|
@click.option("--extra-build-args", help="Supply extra arguments to build")
|
2023-12-05 03:39:16 +00:00
|
|
|
@click.option("--tag", help="Container tag (default: cerc/<app_name>:local)")
|
2023-11-08 00:15:04 +00:00
|
|
|
@click.pass_context
|
2023-12-05 03:39:16 +00:00
|
|
|
def command(ctx, base_container, source_repo, force_rebuild, extra_build_args, tag):
|
2026-01-22 01:58:31 +00:00
|
|
|
"""build the specified webapp container"""
|
2024-02-28 00:38:11 +00:00
|
|
|
logger = TimedLogger()
|
2023-11-08 00:15:04 +00:00
|
|
|
|
|
|
|
|
debug = ctx.obj.debug
|
2024-02-28 00:38:11 +00:00
|
|
|
verbose = ctx.obj.verbose
|
2023-11-08 00:15:04 +00:00
|
|
|
local_stack = ctx.obj.local_stack
|
|
|
|
|
stack = ctx.obj.stack
|
|
|
|
|
|
2026-01-22 01:58:31 +00:00
|
|
|
# See: https://stackoverflow.com/questions/25389095/
|
|
|
|
|
# python-get-path-of-root-project-structure
|
|
|
|
|
container_build_dir = (
|
|
|
|
|
Path(__file__).absolute().parent.parent.joinpath("data", "container-build")
|
|
|
|
|
)
|
2023-11-08 00:15:04 +00:00
|
|
|
|
|
|
|
|
if local_stack:
|
2026-01-22 01:58:31 +00:00
|
|
|
dev_root_path = os.getcwd()[0 : os.getcwd().rindex("stack-orchestrator")]
|
|
|
|
|
logger.log(
|
|
|
|
|
f"Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: "
|
|
|
|
|
f"{dev_root_path}"
|
|
|
|
|
)
|
2023-11-08 00:15:04 +00:00
|
|
|
else:
|
2026-01-22 01:58:31 +00:00
|
|
|
dev_root_path = os.path.expanduser(
|
|
|
|
|
config("CERC_REPO_BASE_DIR", default="~/cerc")
|
|
|
|
|
)
|
2023-11-08 00:15:04 +00:00
|
|
|
|
2024-02-28 00:38:11 +00:00
|
|
|
if verbose:
|
2026-01-22 01:58:31 +00:00
|
|
|
logger.log(f"Dev Root is: {dev_root_path}")
|
2023-11-08 00:15:04 +00:00
|
|
|
|
2024-02-03 00:04:06 +00:00
|
|
|
if not base_container:
|
|
|
|
|
base_container = determine_base_container(source_repo)
|
|
|
|
|
|
2023-11-08 00:15:04 +00:00
|
|
|
# First build the base container.
|
2026-01-22 01:58:31 +00:00
|
|
|
container_build_env = build_containers.make_container_build_env(
|
|
|
|
|
dev_root_path, container_build_dir, debug, force_rebuild, extra_build_args
|
|
|
|
|
)
|
2023-11-08 00:15:04 +00:00
|
|
|
|
2024-02-28 00:38:11 +00:00
|
|
|
if verbose:
|
|
|
|
|
logger.log(f"Building base container: {base_container}")
|
|
|
|
|
|
2024-02-23 19:57:47 +00:00
|
|
|
build_context_1 = BuildContext(
|
|
|
|
|
stack,
|
|
|
|
|
base_container,
|
|
|
|
|
container_build_dir,
|
|
|
|
|
container_build_env,
|
|
|
|
|
dev_root_path,
|
|
|
|
|
)
|
2024-02-24 03:22:49 +00:00
|
|
|
ok = build_containers.process_container(build_context_1)
|
|
|
|
|
if not ok:
|
2024-02-28 00:38:11 +00:00
|
|
|
logger.log("ERROR: Build failed.")
|
2024-02-24 03:22:49 +00:00
|
|
|
sys.exit(1)
|
2023-11-08 00:15:04 +00:00
|
|
|
|
2024-02-28 00:38:11 +00:00
|
|
|
if verbose:
|
|
|
|
|
logger.log(f"Base container {base_container} build finished.")
|
|
|
|
|
|
2026-01-22 01:58:31 +00:00
|
|
|
# Now build the target webapp. We use the same build script,
|
|
|
|
|
# but with a different Dockerfile and work dir.
|
2023-11-09 05:44:48 +00:00
|
|
|
container_build_env["CERC_WEBAPP_BUILD_RUNNING"] = "true"
|
2023-11-08 00:15:04 +00:00
|
|
|
container_build_env["CERC_CONTAINER_BUILD_WORK_DIR"] = os.path.abspath(source_repo)
|
2026-01-22 01:58:31 +00:00
|
|
|
container_build_env["CERC_CONTAINER_BUILD_DOCKERFILE"] = os.path.join(
|
|
|
|
|
container_build_dir, base_container.replace("/", "-"), "Dockerfile.webapp"
|
|
|
|
|
)
|
2023-12-05 03:39:16 +00:00
|
|
|
if not tag:
|
|
|
|
|
webapp_name = os.path.abspath(source_repo).split(os.path.sep)[-1]
|
2024-02-28 00:38:11 +00:00
|
|
|
tag = f"cerc/{webapp_name}:local"
|
|
|
|
|
|
|
|
|
|
container_build_env["CERC_CONTAINER_BUILD_TAG"] = tag
|
|
|
|
|
|
|
|
|
|
if verbose:
|
|
|
|
|
logger.log(f"Building app container: {tag}")
|
2023-11-08 00:15:04 +00:00
|
|
|
|
2024-02-23 19:57:47 +00:00
|
|
|
build_context_2 = BuildContext(
|
|
|
|
|
stack,
|
|
|
|
|
base_container,
|
|
|
|
|
container_build_dir,
|
|
|
|
|
container_build_env,
|
|
|
|
|
dev_root_path,
|
|
|
|
|
)
|
2024-02-24 03:22:49 +00:00
|
|
|
ok = build_containers.process_container(build_context_2)
|
|
|
|
|
if not ok:
|
2024-02-28 00:38:11 +00:00
|
|
|
logger.log("ERROR: Build failed.")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
if verbose:
|
|
|
|
|
logger.log(f"App container {base_container} build finished.")
|
|
|
|
|
logger.log("build-webapp complete", show_step_time=False, show_total_time=True)
|