itw-python-builder 0.1.37__tar.gz → 0.1.39__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/PKG-INFO +1 -1
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/tasks.py +20 -24
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/utils.py +39 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/PKG-INFO +1 -1
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/pyproject.toml +1 -1
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/LICENSE +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/README.md +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/.pylintrc +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/__init__.py +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/cli.py +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/ssr_tasks.py +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/templates/server.sitemap.snippet.ts +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/templates/sitemap.routes.ts +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder/version.py +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/SOURCES.txt +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/dependency_links.txt +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/entry_points.txt +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/requires.txt +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/top_level.txt +0 -0
- {itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/setup.cfg +0 -0
|
@@ -12,6 +12,9 @@ from itw_python_builder.utils import (
|
|
|
12
12
|
get_gitlab_username,
|
|
13
13
|
_parse_gitlab_remote,
|
|
14
14
|
is_ssr_project,
|
|
15
|
+
install_sigint_guard,
|
|
16
|
+
abort_if_interrupted,
|
|
17
|
+
step,
|
|
15
18
|
)
|
|
16
19
|
from itw_python_builder.ssr_tasks import * # noqa: F401,F403 — exposes ssr-init
|
|
17
20
|
|
|
@@ -61,18 +64,9 @@ def build_frontend(ctx: Context, branch: str, ssr: bool = False) -> None:
|
|
|
61
64
|
|
|
62
65
|
def package_dist(ctx: Context) -> None:
|
|
63
66
|
"""Tar the dist/ output directory into dist.tar.gz."""
|
|
64
|
-
|
|
65
|
-
if not os.path.isdir(dist_dir):
|
|
67
|
+
if not os.path.isdir(os.path.join(os.getcwd(), 'dist')):
|
|
66
68
|
raise RuntimeError('No dist/ directory found after build — did `ng build` succeed?')
|
|
67
|
-
|
|
68
|
-
target_dir = dist_dir
|
|
69
|
-
if not is_ssr_project():
|
|
70
|
-
for root, dirs, files in os.walk(dist_dir):
|
|
71
|
-
if 'index.html' in files:
|
|
72
|
-
target_dir = root
|
|
73
|
-
break
|
|
74
|
-
|
|
75
|
-
ctx.run(f'tar -czf dist.tar.gz -C "{target_dir}" .')
|
|
69
|
+
ctx.run('tar -czf dist.tar.gz -C dist .')
|
|
76
70
|
|
|
77
71
|
|
|
78
72
|
_GITLAB_API_HOST_MAP = {
|
|
@@ -133,21 +127,22 @@ def pushimage(ctx: Context):
|
|
|
133
127
|
|
|
134
128
|
|
|
135
129
|
def tag_build_push(ctx: Context, version: Version, skip_pipeline: bool = False, ssr: bool = False) -> None:
|
|
130
|
+
install_sigint_guard()
|
|
136
131
|
project_type = detect_project_type()
|
|
137
132
|
if not skip_pipeline:
|
|
138
|
-
test
|
|
139
|
-
analyze
|
|
140
|
-
tag
|
|
133
|
+
step('tests', test, ctx)
|
|
134
|
+
step('analyze', analyze, ctx)
|
|
135
|
+
step('tag', tag, ctx, version)
|
|
141
136
|
if project_type == 'backend':
|
|
142
|
-
buildimage
|
|
143
|
-
pushimage
|
|
137
|
+
step('build image', buildimage, ctx)
|
|
138
|
+
step('push image', pushimage, ctx)
|
|
144
139
|
else:
|
|
145
140
|
branch = get_current_branch(ctx)
|
|
146
|
-
build_frontend
|
|
147
|
-
package_dist
|
|
148
|
-
upload_dist
|
|
149
|
-
changelog
|
|
150
|
-
push
|
|
141
|
+
step('build', build_frontend, ctx, branch, ssr=ssr)
|
|
142
|
+
step('package', package_dist, ctx)
|
|
143
|
+
step('upload', upload_dist, ctx, version)
|
|
144
|
+
step('changelog', changelog, ctx, version)
|
|
145
|
+
step('push', push, ctx)
|
|
151
146
|
|
|
152
147
|
|
|
153
148
|
@task(name='tag-init')
|
|
@@ -364,23 +359,24 @@ def analyzelocal(ctx: Context):
|
|
|
364
359
|
@task
|
|
365
360
|
def pipelinelocal(ctx: Context, settings='backend.test_settings', pylintrc=None):
|
|
366
361
|
"""Local pipeline: (lint →) test → analyze"""
|
|
362
|
+
install_sigint_guard()
|
|
367
363
|
project_type = detect_project_type()
|
|
368
364
|
if project_type == 'backend':
|
|
369
365
|
detect_and_activate_venv()
|
|
370
366
|
print("=" * 60)
|
|
371
367
|
print("Step 1: Running lint...")
|
|
372
368
|
print("=" * 60)
|
|
373
|
-
lint
|
|
369
|
+
step('lint', lint, ctx, pylintrc=pylintrc)
|
|
374
370
|
|
|
375
371
|
print("\n" + "=" * 60)
|
|
376
372
|
print(f"Step {'2' if project_type == 'backend' else '1'}: Running tests...")
|
|
377
373
|
print("=" * 60)
|
|
378
|
-
testlocal
|
|
374
|
+
step('tests', testlocal, ctx, settings)
|
|
379
375
|
|
|
380
376
|
print("\n" + "=" * 60)
|
|
381
377
|
print(f"Step {'3' if project_type == 'backend' else '2'}: Running SonarQube analysis...")
|
|
382
378
|
print("=" * 60)
|
|
383
|
-
analyzelocal
|
|
379
|
+
step('analyze', analyzelocal, ctx)
|
|
384
380
|
|
|
385
381
|
print("\n" + "=" * 60)
|
|
386
382
|
print("✓ Local pipeline completed successfully!")
|
|
@@ -7,6 +7,8 @@ import io
|
|
|
7
7
|
import json
|
|
8
8
|
import os
|
|
9
9
|
import re
|
|
10
|
+
import signal
|
|
11
|
+
import sys
|
|
10
12
|
from pathlib import Path
|
|
11
13
|
|
|
12
14
|
from invoke import Context
|
|
@@ -15,6 +17,43 @@ from itw_python_builder.version import Version
|
|
|
15
17
|
|
|
16
18
|
_venv_activated = False
|
|
17
19
|
|
|
20
|
+
_INTERRUPTED = False
|
|
21
|
+
_SIGINT_INSTALLED = False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _sigint_handler(signum, frame):
|
|
25
|
+
global _INTERRUPTED
|
|
26
|
+
_INTERRUPTED = True
|
|
27
|
+
raise KeyboardInterrupt
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def install_sigint_guard() -> None:
|
|
31
|
+
"""Install a process-wide SIGINT trap."""
|
|
32
|
+
global _SIGINT_INSTALLED
|
|
33
|
+
if _SIGINT_INSTALLED:
|
|
34
|
+
return
|
|
35
|
+
signal.signal(signal.SIGINT, _sigint_handler)
|
|
36
|
+
_SIGINT_INSTALLED = True
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def abort_if_interrupted(step: str = '') -> None:
|
|
40
|
+
"""Exit 130 if a SIGINT was received since the last call."""
|
|
41
|
+
if _INTERRUPTED:
|
|
42
|
+
where = f' during {step}' if step else ''
|
|
43
|
+
print(f'\n[itw] Aborted by user (Ctrl+C){where}.')
|
|
44
|
+
sys.exit(130)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def step(label: str, fn, *args, **kwargs):
|
|
48
|
+
"""Run `fn(*args, **kwargs)`, swallow KeyboardInterrupt, then bail if SIGINT was seen."""
|
|
49
|
+
result = None
|
|
50
|
+
try:
|
|
51
|
+
result = fn(*args, **kwargs)
|
|
52
|
+
except KeyboardInterrupt:
|
|
53
|
+
pass
|
|
54
|
+
abort_if_interrupted(label)
|
|
55
|
+
return result
|
|
56
|
+
|
|
18
57
|
|
|
19
58
|
def detect_project_type() -> str:
|
|
20
59
|
"""Detect whether the current directory is a 'frontend' or 'backend' project."""
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "itw_python_builder"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.39"
|
|
8
8
|
description = "Standardized Django deployment pipeline with Docker, testing, and SonarQube integration"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/requires.txt
RENAMED
|
File without changes
|
{itw_python_builder-0.1.37 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|