itw-python-builder 0.1.38__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.38 → itw_python_builder-0.1.39}/PKG-INFO +1 -1
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/tasks.py +18 -13
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/utils.py +39 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/PKG-INFO +1 -1
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/pyproject.toml +1 -1
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/LICENSE +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/README.md +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/.pylintrc +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/__init__.py +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/cli.py +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/ssr_tasks.py +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/templates/server.sitemap.snippet.ts +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/templates/sitemap.routes.ts +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder/version.py +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/SOURCES.txt +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/dependency_links.txt +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/entry_points.txt +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/requires.txt +0 -0
- {itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/top_level.txt +0 -0
- {itw_python_builder-0.1.38 → 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
|
|
|
@@ -124,21 +127,22 @@ def pushimage(ctx: Context):
|
|
|
124
127
|
|
|
125
128
|
|
|
126
129
|
def tag_build_push(ctx: Context, version: Version, skip_pipeline: bool = False, ssr: bool = False) -> None:
|
|
130
|
+
install_sigint_guard()
|
|
127
131
|
project_type = detect_project_type()
|
|
128
132
|
if not skip_pipeline:
|
|
129
|
-
test
|
|
130
|
-
analyze
|
|
131
|
-
tag
|
|
133
|
+
step('tests', test, ctx)
|
|
134
|
+
step('analyze', analyze, ctx)
|
|
135
|
+
step('tag', tag, ctx, version)
|
|
132
136
|
if project_type == 'backend':
|
|
133
|
-
buildimage
|
|
134
|
-
pushimage
|
|
137
|
+
step('build image', buildimage, ctx)
|
|
138
|
+
step('push image', pushimage, ctx)
|
|
135
139
|
else:
|
|
136
140
|
branch = get_current_branch(ctx)
|
|
137
|
-
build_frontend
|
|
138
|
-
package_dist
|
|
139
|
-
upload_dist
|
|
140
|
-
changelog
|
|
141
|
-
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)
|
|
142
146
|
|
|
143
147
|
|
|
144
148
|
@task(name='tag-init')
|
|
@@ -355,23 +359,24 @@ def analyzelocal(ctx: Context):
|
|
|
355
359
|
@task
|
|
356
360
|
def pipelinelocal(ctx: Context, settings='backend.test_settings', pylintrc=None):
|
|
357
361
|
"""Local pipeline: (lint →) test → analyze"""
|
|
362
|
+
install_sigint_guard()
|
|
358
363
|
project_type = detect_project_type()
|
|
359
364
|
if project_type == 'backend':
|
|
360
365
|
detect_and_activate_venv()
|
|
361
366
|
print("=" * 60)
|
|
362
367
|
print("Step 1: Running lint...")
|
|
363
368
|
print("=" * 60)
|
|
364
|
-
lint
|
|
369
|
+
step('lint', lint, ctx, pylintrc=pylintrc)
|
|
365
370
|
|
|
366
371
|
print("\n" + "=" * 60)
|
|
367
372
|
print(f"Step {'2' if project_type == 'backend' else '1'}: Running tests...")
|
|
368
373
|
print("=" * 60)
|
|
369
|
-
testlocal
|
|
374
|
+
step('tests', testlocal, ctx, settings)
|
|
370
375
|
|
|
371
376
|
print("\n" + "=" * 60)
|
|
372
377
|
print(f"Step {'3' if project_type == 'backend' else '2'}: Running SonarQube analysis...")
|
|
373
378
|
print("=" * 60)
|
|
374
|
-
analyzelocal
|
|
379
|
+
step('analyze', analyzelocal, ctx)
|
|
375
380
|
|
|
376
381
|
print("\n" + "=" * 60)
|
|
377
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.38 → 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.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/requires.txt
RENAMED
|
File without changes
|
{itw_python_builder-0.1.38 → itw_python_builder-0.1.39}/itw_python_builder.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|