diff --git a/{{cookiecutter.project_slug}}/Dockerfile b/{{cookiecutter.project_slug}}/Dockerfile index ee38ec0..4c9fff4 100644 --- a/{{cookiecutter.project_slug}}/Dockerfile +++ b/{{cookiecutter.project_slug}}/Dockerfile @@ -13,6 +13,7 @@ WORKDIR /app COPY --from=builder /app/requirements.txt /app/dist/*.whl ./ RUN pip install --no-cache-dir -r requirements.txt \ && pip install --no-cache-dir --no-deps *.whl \ + && python -c "import {{ cookiecutter.package_name }}" \ && rm -f *.whl requirements.txt USER 1000:1000 ENTRYPOINT ["python", "-m", "{{ cookiecutter.package_name }}"] diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index 248690b..d4b1bd7 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -65,3 +65,6 @@ ignore = [ [tool.ruff.lint.per-file-ignores] "tests/*" = ["ARG001"] # Allow unused arguments in tests + +[tool.ruff.lint.isort] +known-first-party = ["{{ cookiecutter.package_name }}"] diff --git a/{{cookiecutter.project_slug}}/tasks.py b/{{cookiecutter.project_slug}}/tasks.py index 7844df8..e4d106e 100644 --- a/{{cookiecutter.project_slug}}/tasks.py +++ b/{{cookiecutter.project_slug}}/tasks.py @@ -58,6 +58,7 @@ def bump(c, part): if c.run("git status --porcelain", hide=True).stdout.strip(): raise SystemExit("Working tree is dirty. Commit or stash changes first.") + c.run("git fetch --tags", hide=True) major, minor, patch = (int(x) for x in _latest_tag(c).lstrip("v").split(".")) if part == "major": major, minor, patch = major + 1, 0, 0 @@ -68,7 +69,8 @@ def bump(c, part): tag = f"v{major}.{minor}.{patch}" c.run(f"git tag {tag}") - print(f"Tagged {tag}. Push it with: git push origin {tag}") + c.run(f"git push origin {tag}") + print(f"Tagged and pushed {tag}.") {%- if cookiecutter.project_type == "service" %} @@ -77,25 +79,30 @@ def _version(c) -> str: @task +def version(c): + """Print the current version (latest git tag).""" + print(_version(c)) + + +@task(pre=[ci]) def build_image(c): - """Build the runtime image, tagged with the current version.""" - c.run(f"docker build --network=host -t {IMAGE}:{_version(c)} .") + """Build the runtime image tagged as latest.""" + c.run(f"docker build --network=host -t {IMAGE}:latest .") @task def deploy(c): - """Build image, copy to VPS over SSH, restart the compose service.""" - version = _version(c) + """Build image, copy to VPS over SSH, then prompt before restarting the compose service.""" build_image(c) - print(f"Transferring {IMAGE}:{version} to {VPS}...") - c.run(f"docker save {IMAGE}:{version} | ssh {VPS} docker load", pty=True) - print("Updating docker-compose and restarting service...") - c.run( - f'ssh {VPS} "cd {REMOTE_DIR} && ' - f"sed -i 's|image: {IMAGE}:.*|image: {IMAGE}:{version}|' docker-compose.yml && " - f'docker compose up -d {SERVICE}"' - ) - print(f"Deployed {IMAGE}:{version}") + print(f"Transferring {IMAGE}:latest to {VPS}...") + c.run(f"docker save {IMAGE}:latest | ssh {VPS} docker load", pty=True) + print("Image transferred.") + answer = input("Restart service on VPS? [y/N] ").strip().lower() + if answer != "y": + print("Skipping restart. Image is available on the VPS.") + return + c.run(f'ssh {VPS} "cd {REMOTE_DIR} && docker compose down {SERVICE} && docker compose up -d {SERVICE}"') + print("Service restarted.") {%- endif %}