Skip to content

Commit

Permalink
fix(install): strict healthcheck, better version parsing, install fix…
Browse files Browse the repository at this point in the history
…es (#496)
  • Loading branch information
ocervell authored Nov 28, 2024
1 parent 3140ee2 commit 7d6e071
Show file tree
Hide file tree
Showing 13 changed files with 229 additions and 60 deletions.
5 changes: 5 additions & 0 deletions .github/actions/install/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: Install secator
description: Installs secator
inputs:
python-version:
description: "Python version"
required: true
runs:
using: "composite"
Expand All @@ -15,3 +16,7 @@ runs:
- name: Install secator with pipx
shell: bash
run: pipx install -e .[dev]

- name: Add secator to $PATH
shell: bash
run: echo "$HOME/.local/bin" >> "$GITHUB_PATH"
38 changes: 38 additions & 0 deletions .github/workflows/release-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: release-test

on:
push:
branches:
- release-please*

permissions:
contents: write
pull-requests: write

jobs:
test-docker:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11"]
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Install secator
uses: ./.github/actions/install
with:
python-version: ${{ matrix.python-version }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
run: secator u build docker

- name: Run secator health check (strict)
run: docker run -it --privileged freelabz/secator:dev health --strict
74 changes: 59 additions & 15 deletions secator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,8 @@ def report_export(json_path, output_folder, output):
@cli.command(name='health')
@click.option('--json', '-json', is_flag=True, default=False, help='JSON lines output')
@click.option('--debug', '-debug', is_flag=True, default=False, help='Debug health output')
def health(json, debug):
@click.option('--strict', '-strict', is_flag=True, default=False, help='Fail if missing tools')
def health(json, debug, strict):
"""[dim]Get health status.[/]"""
tools = ALL_TASKS
status = {'secator': {}, 'languages': {}, 'tools': {}, 'addons': {}}
Expand Down Expand Up @@ -870,10 +871,7 @@ def health(json, debug):
table = get_health_table()
with Live(table, console=console):
for tool in tools:
cmd = tool.cmd.split(' ')[0]
version_flag = tool.version_flag or f'{tool.opt_prefix}version'
version_flag = None if tool.version_flag == OPT_NOT_SUPPORTED else version_flag
info = get_version_info(cmd, version_flag, tool.install_github_handle)
info = get_version_info(tool.cmd.split(' ')[0], tool.version_flag, tool.install_github_handle, tool.install_cmd)
row = fmt_health_table_row(info, 'tools')
table.add_row(*row)
status['tools'][tool.__name__] = info
Expand All @@ -883,6 +881,18 @@ def health(json, debug):
import json as _json
print(_json.dumps(status))

# Strict mode
if strict:
error = False
for tool, info in status['tools'].items():
if not info['installed']:
console.print(f'[bold red]{tool} not installed and strict mode is enabled.[/]')
error = True
if error:
sys.exit(1)
console.print('[bold green]Strict healthcheck passed ![/]')


#---------#
# INSTALL #
#---------#
Expand Down Expand Up @@ -1066,11 +1076,15 @@ def install_tools(cmds):
tools = [cls for cls in ALL_TASKS if cls.__name__ in cmds]
else:
tools = ALL_TASKS

return_code = 0
for ix, cls in enumerate(tools):
with console.status(f'[bold yellow][{ix}/{len(tools)}] Installing {cls.__name__} ...'):
ToolInstaller.install(cls)
status = ToolInstaller.install(cls)
if not status.is_ok():
console.print(f'[bold red]Failed installing {cls.__name__}[/]')
return_code = 1
console.print()
sys.exit(return_code)


@install.command('cves')
Expand Down Expand Up @@ -1103,22 +1117,52 @@ def install_cves(force):
#--------#

@cli.command('update')
def update():
@click.option('--all', '-a', is_flag=True, help='Update all secator dependencies (addons, tools, ...)')
def update(all):
"""[dim]Update to latest version.[/]"""
if CONFIG.offline_mode:
console.print('[bold red]Cannot run this command in offline mode.[/]')
return
sys.exit(1)

# Check current and latest version
info = get_version_info('secator', github_handle='freelabz/secator', version=VERSION)
latest_version = info['latest_version']
do_update = True

# Skip update if latest
if info['status'] == 'latest':
console.print(f'[bold green]secator is already at the newest version {latest_version}[/] !')
sys.exit(0)
console.print(f'[bold gold3]:wrench: Updating secator from {VERSION} to {latest_version} ...[/]')
if 'pipx' in sys.executable:
Command.execute(f'pipx install secator=={latest_version} --force')
else:
Command.execute(f'pip install secator=={latest_version}')
do_update = False

# Fail if unknown latest
if not latest_version:
console.print('[bold red]Could not fetch latest secator version.[/]')
sys.exit(1)

# Update secator
if do_update:
console.print(f'[bold gold3]:wrench: Updating secator from {VERSION} to {latest_version} ...[/]')
if 'pipx' in sys.executable:
ret = Command.execute(f'pipx install secator=={latest_version} --force')
else:
ret = Command.execute(f'pip install secator=={latest_version}')
if not ret.return_code == 0:
sys.exit(1)

# Update tools
if all:
return_code = 0
for cls in ALL_TASKS:
cmd = cls.cmd.split(' ')[0]
version_flag = cls.version_flag or f'{cls.opt_prefix}version'
version_flag = None if cls.version_flag == OPT_NOT_SUPPORTED else version_flag
info = get_version_info(cmd, version_flag, cls.install_github_handle)
if not info['installed'] or info['status'] == 'outdated' or not info['latest_version']:
with console.status(f'[bold yellow]Installing {cls.__name__} ...'):
status = ToolInstaller.install(cls)
if not status.is_ok():
return_code = 1
sys.exit(return_code)

#-------#
# ALIAS #
Expand Down
2 changes: 1 addition & 1 deletion secator/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Celery(StrictModel):


class Cli(StrictModel):
github_token: str = ''
github_token: str = os.environ.get('GITHUB_TOKEN', '')
record: bool = False
stdin_timeout: int = 1000

Expand Down
Loading

0 comments on commit 7d6e071

Please sign in to comment.