Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ jobs:
ruff format --check ./ctf
ruff check ./ctf

- name: ctf init
- name: CTF init
run: |
ctf init test-ctf
ctf --no-update-check init test-ctf

- name: Copy CTF files
run: |
Expand All @@ -56,22 +56,22 @@ jobs:
ls -al test-ctf/
ls -al test-ctf/challenges

- name: ctf version
- name: CTF version
working-directory: test-ctf
run: |
ctf version
ctf --no-update-check version

- name: CTF stats
# Run this in the test-ctf directory
working-directory: test-ctf
run: |
ctf stats
ctf --no-update-check stats

- name: CTF list
# Run this in the test-ctf directory
working-directory: test-ctf
run: |
ctf list
ctf --no-update-check list

- name: Remove docker
run: |
Expand Down Expand Up @@ -148,17 +148,17 @@ jobs:
# Run this in the test-ctf directory
working-directory: test-ctf
run: |
ctf validate
ctf --no-update-check validate

- name: Deployment check
working-directory: test-ctf
run: |
ctf check
ctf --no-update-check check

- name: File generation
working-directory: test-ctf
run: |
ctf generate
ctf --no-update-check generate

- name: Test deployment looping through tracks
working-directory: test-ctf
Expand All @@ -169,33 +169,33 @@ jobs:

for track in "${tracks[@]}"
do
ctf deploy --production --tracks "$track"
ctf --no-update-check deploy --production --tracks "$track"
incus --project="$track" info "$track"
done

ctf destroy --force
ctf --no-update-check destroy --force

- name: Test full deployment
working-directory: test-ctf
run: |
ctf deploy --production
ctf --no-update-check deploy --production
[ "$(incus list --all-projects -cn -fcsv | wc -l)" -eq 2 ] || exit 1
ctf destroy --force
ctf --no-update-check destroy --force

- name: Test redeployment of Mock Track Apache PHP
working-directory: test-ctf
run: |
ctf deploy --production
ctf --no-update-check deploy --production
[ "$(incus list --all-projects -cn -fcsv | wc -l)" -eq 2 ] || exit 1
ctf redeploy --production --tracks mock-track-apache-php
ctf --no-update-check redeploy --production --tracks mock-track-apache-php
[ "$(incus list --all-projects -cn -fcsv | wc -l)" -eq 2 ] || exit 1
ctf destroy --force
ctf --no-update-check destroy --force

- name: Test deployment of a track not deployed without destroying the rest
working-directory: test-ctf
run: |
ctf deploy --production --tracks mock-track-apache-php
ctf --no-update-check deploy --production --tracks mock-track-apache-php
[ "$(incus list --all-projects -cn -fcsv | wc -l)" -eq 1 ] || exit 1
ctf redeploy --production --tracks mock-track-python-service
ctf --no-update-check redeploy --production --tracks mock-track-python-service
[ "$(incus list --all-projects -cn -fcsv | wc -l)" -eq 2 ] || exit 1
ctf destroy --force
ctf --no-update-check destroy --force
56 changes: 0 additions & 56 deletions ctf/__init__.py
Original file line number Diff line number Diff line change
@@ -1,63 +1,7 @@
#!/usr/bin/env python3
import importlib.metadata
import json
import os
import sys
import urllib.request

from ctf.logger import LOG

VERSION = importlib.metadata.version("ctf-script")

if len(sys.argv) > 1 and sys.argv[1] == "version":
print(VERSION)
exit(code=0)


ENV = {}
STATE = {"verbose": False}
for k, v in os.environ.items():
ENV[k] = v


def check_tool_version() -> None:
try:
r_context = urllib.request.urlopen(
url="https://api.github.com/repos/nsec/ctf-script/releases/latest"
)
except Exception as e:
LOG.debug(e)
LOG.warning("Could not verify the latest release.")
return
with r_context as r:
try:
latest_version = json.loads(s=r.read().decode())["tag_name"]
except Exception as e:
LOG.debug(e)
LOG.error("Could not verify the latest release.")
return

compare = 0
for current_part, latest_part in zip(
[int(part) for part in VERSION.split(".")],
[int(part) for part in latest_version.split(".")],
):
if current_part < latest_part:
compare = -1
break
elif current_part > latest_part:
compare = 1
break

match compare:
case 0 | 1:
LOG.debug("Script is up to date.")
case -1:
LOG.warning(
f"Script is outdated (current: {VERSION}, upstream: {latest_version}). Please update to the latest release before continuing."
)
if (input("Do you want to continue? [y/N] ").lower() or "n") == "n":
exit(code=0)


check_tool_version()
70 changes: 68 additions & 2 deletions ctf/__main__.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
#!/usr/bin/env python3
import json
import logging
import os
import sys
import urllib.request

import rich
import typer
from rich.console import Console
from typer import Typer
from typing_extensions import Annotated

from ctf import ENV, LOG, STATE
from ctf import ENV, STATE
from ctf.check import app as check_app
from ctf.deploy import app as deploy_app
from ctf.destroy import app as destroy_app
from ctf.flags import app as flags_app
from ctf.generate import app as generate_app
from ctf.init import app as init_app
from ctf.list import app as list_app
from ctf.logger import LOG
from ctf.new import app as new_app
from ctf.redeploy import app as redeploy_app
from ctf.services import app as services_app
from ctf.stats import app as stats_app
from ctf.utils import find_ctf_root_directory
from ctf.utils import find_ctf_root_directory, get_version, show_version
from ctf.validate import app as validate_app
from ctf.version import app as version_app

Expand All @@ -41,14 +46,72 @@
app.add_typer(version_app)


def check_tool_version() -> None:
with Console().status("Checking for updates..."):
current_version = get_version()
try:
r_context = urllib.request.urlopen(
url="https://api.github.com/repos/nsec/ctf-script/releases/latest"
)
except Exception as e:
LOG.debug(e)
LOG.warning("Could not verify the latest release.")
return
with r_context as r:
try:
latest_version = json.loads(s=r.read().decode())["tag_name"]
except Exception as e:
LOG.debug(e)
LOG.error("Could not verify the latest release.")
return

compare = 0
for current_part, latest_part in zip(
[int(part) for part in current_version.split(".")],
[int(part) for part in latest_version.split(".")],
):
if current_part < latest_part:
compare = -1
break
elif current_part > latest_part:
compare = 1
break

match compare:
case 0 | 1:
LOG.debug("Script is up to date.")
case -1:
LOG.warning(
f"Script is outdated (current: {current_version}, upstream: {latest_version}). Please update to the latest release before continuing."
)
if (input("Do you want to continue? [y/N] ").lower() or "n") == "n":
exit(code=0)


@app.callback()
def global_options(
location: Annotated[
str, typer.Option("--location", help="CTF root directory location.")
] = "",
no_update_check: Annotated[
bool,
typer.Option(
"--no-update-check", help="Do not check for update.", is_flag=True
),
] = False,
verbose: Annotated[
bool, typer.Option("--verbose", "-v", help="Enable DEBUG logging.")
] = False,
version: Annotated[
bool | None,
typer.Option(
"--version",
show_default=False,
is_eager=True,
callback=show_version,
help="Show version",
),
] = None,
):
if verbose:
LOG.setLevel(logging.DEBUG)
Expand All @@ -58,6 +121,9 @@ def global_options(
if location:
ENV["CTF_ROOT_DIR"] = location

if not no_update_check:
check_tool_version()


def main():
# Set console width to 150 if it's smaller to avoid "…" in output
Expand Down
4 changes: 0 additions & 4 deletions ctf/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,3 @@ class TrackYaml(BaseModel):
instances: TrackInstances | None = None
flags: list[TrackFlag]
services: list[DeprecatedTrackService] | None = None


# TrackInstances.model_rebuild()
# TrackYaml.model_rebuild()
13 changes: 13 additions & 0 deletions ctf/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import importlib.metadata
import os
import re
import shutil
Expand All @@ -6,6 +7,7 @@
from typing import Any, Generator

import jinja2
import typer
import yaml

from ctf import ENV
Expand Down Expand Up @@ -392,6 +394,17 @@ def is_ctf_dir(path):
return ctf_dir


def get_version() -> str:
return importlib.metadata.version("ctf-script")


def show_version(value: bool) -> None:
# If --version option is present, show the version and exit
if value:
typer.echo(f"ctf-script v{get_version()}")
raise typer.Exit()


def terraform_binary() -> str:
path = shutil.which(cmd="tofu")
if not path:
Expand Down
2 changes: 1 addition & 1 deletion ctf/validate_json_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)
from rich.table import Table

from ctf import LOG
from ctf.logger import LOG


def validate_with_json_schemas(schema: str, files_pattern: str) -> None:
Expand Down
5 changes: 2 additions & 3 deletions ctf/version.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import typer

from ctf import VERSION
from ctf.utils import show_version

app = typer.Typer()


@app.command(help="Print the tool's version.")
def version():
print(VERSION)
exit(0)
show_version(True)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ dependencies = [
"typer==0.16.0",
"pydantic"
]
version = "4.3.2"
version = "4.3.3"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
Expand Down
Loading