Compare commits

...

5 Commits

Author SHA1 Message Date
Kevin Veen-Birkenbach
fb737ef290 Optimized Changelog
Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled
2025-12-13 08:40:37 +01:00
Kevin Veen-Birkenbach
2963a43754 **Refactor README: streamline rationale, features, install and run sections**
* Simplify *Why PKGMGR* into concise prose and add Docker images as reproducible system baselines linked to Infinito.Nexus
* Condense Features into a single, readable overview without command lists
* Clean up Architecture section and keep diagram metadata consistent
* Reorganize Installation with clear download, dependencies, install and setup modes
* Introduce a unified *Run PKGMGR* section differentiating Nix, Docker and venv usage with consistent examples
2025-12-13 08:34:39 +01:00
Kevin Veen-Birkenbach
103f49c8f6 Release version 1.4.1
Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled
2025-12-12 23:06:15 +01:00
Kevin Veen-Birkenbach
f5d428950e **Replace main.py with module-based entry point and unify CLI execution**
Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled
* Remove legacy *main.py* and introduce *pkgmgr* module entry via *python -m pkgmgr*
* Add ***main**.py* as the canonical entry point delegating to the CLI
* Export *PYTHONPATH=src* in Makefile to ensure reliable imports in dev and CI
* Update setup scripts (venv & nix) to use module execution
* Refactor all E2E tests to execute the real module entry instead of file paths

This aligns pkgmgr with standard Python packaging practices and simplifies testing, setup, and execution across environments.

https://chatgpt.com/share/693c9056-716c-800f-b583-fc9245eab2b4
2025-12-12 22:59:46 +01:00
Kevin Veen-Birkenbach
b40787ffc5 ci: publish GHCR images after successful mark-stable workflow
Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled
Trigger container publishing via workflow_run on "Mark stable commit", gate on success,
checkout the workflow_run head SHA, force-refresh tags, and derive version from the v* tag
pointing at the tested commit to correctly detect and publish stable images.

https://chatgpt.com/share/693c836b-0b00-800f-9536-9e273abd0fb5
2025-12-12 22:50:33 +01:00
25 changed files with 164 additions and 156 deletions

View File

@@ -1,12 +1,13 @@
name: Publish container images (GHCR) name: Publish container images (GHCR)
on: on:
push: workflow_run:
tags: workflows: ["Mark stable commit"]
- "v*" types: [completed]
jobs: jobs:
publish: publish:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
@@ -20,13 +21,22 @@ jobs:
fetch-depth: 0 fetch-depth: 0
fetch-tags: true fetch-tags: true
- name: Checkout workflow_run commit and refresh tags
run: |
set -euo pipefail
git checkout -f "${{ github.event.workflow_run.head_sha }}"
git fetch --tags --force
git tag --list 'stable' 'v*' --sort=version:refname | tail -n 20
- name: Compute version and stable flag - name: Compute version and stable flag
id: info id: info
run: | run: |
set -euo pipefail set -euo pipefail
SHA="$(git rev-parse HEAD)" SHA="$(git rev-parse HEAD)"
VERSION="${GITHUB_REF_NAME#v}"
V_TAG="$(git tag --points-at "${SHA}" --list 'v*' | sort -V | tail -n1)"
[[ -n "$V_TAG" ]] || { echo "No version tag found"; exit 1; }
VERSION="${V_TAG#v}"
STABLE_SHA="$(git rev-parse -q --verify refs/tags/stable^{commit} 2>/dev/null || true)" STABLE_SHA="$(git rev-parse -q --verify refs/tags/stable^{commit} 2>/dev/null || true)"
IS_STABLE=false IS_STABLE=false

View File

@@ -1,6 +1,11 @@
## [1.4.1] - 2025-12-12
* Fixed stable release container publishing
## [1.4.0] - 2025-12-12 ## [1.4.0] - 2025-12-12
* **Docker Container Building** **Docker Container Building**
* New official container images are automatically published on each release. * New official container images are automatically published on each release.
* Images are available per distribution and as a default Arch-based image. * Images are available per distribution and as a default Arch-based image.
@@ -14,7 +19,7 @@
## [1.3.0] - 2025-12-12 ## [1.3.0] - 2025-12-12
* **Minor release Stability & CI hardening** **Stability & CI hardening**
* Stabilized Nix resolution and global symlink handling across Arch, CentOS, Debian, and Ubuntu * Stabilized Nix resolution and global symlink handling across Arch, CentOS, Debian, and Ubuntu
* Ensured Nix works reliably in CI, sudo, login, and non-login shells without overriding distro-managed paths * Ensured Nix works reliably in CI, sudo, login, and non-login shells without overriding distro-managed paths
@@ -26,7 +31,7 @@
## [1.2.1] - 2025-12-12 ## [1.2.1] - 2025-12-12
* **Changed** **Changed**
* Split container tests into *virtualenv* and *Nix flake* environments to clearly separate Python and Nix responsibilities. * Split container tests into *virtualenv* and *Nix flake* environments to clearly separate Python and Nix responsibilities.
@@ -43,7 +48,7 @@
## [1.2.0] - 2025-12-12 ## [1.2.0] - 2025-12-12
* **Release workflow overhaul** **Release workflow overhaul**
* Introduced a fully structured release workflow with clear phases and safeguards * Introduced a fully structured release workflow with clear phases and safeguards
* Added preview-first releases with explicit confirmation before execution * Added preview-first releases with explicit confirmation before execution
@@ -60,7 +65,8 @@
## [1.0.0] - 2025-12-11 ## [1.0.0] - 2025-12-11
* **1.0.0 Official Stable Release 🎉** **Official Stable Release 🎉**
*First stable release of PKGMGR, the multi-distro development and package workflow manager.* *First stable release of PKGMGR, the multi-distro development and package workflow manager.*
--- ---
@@ -153,7 +159,7 @@ PKGMGR 1.0.0 unifies repository management, build tooling, release automation an
## [0.9.1] - 2025-12-10 ## [0.9.1] - 2025-12-10
* * Refactored installer: new `venv-create.sh`, cleaner root/user setup flow, updated README with architecture map. * Refactored installer: new `venv-create.sh`, cleaner root/user setup flow, updated README with architecture map.
* Split virgin tests into root/user workflows; stabilized Nix installer across distros; improved test scripts with dynamic distro selection and isolated Nix stores. * Split virgin tests into root/user workflows; stabilized Nix installer across distros; improved test scripts with dynamic distro selection and isolated Nix stores.
* Fixed repository directory resolution; improved `pkgmgr path` and `pkgmgr shell`; added full unit/E2E coverage. * Fixed repository directory resolution; improved `pkgmgr path` and `pkgmgr shell`; added full unit/E2E coverage.
* Removed deprecated files and updated `.gitignore`. * Removed deprecated files and updated `.gitignore`.
@@ -248,47 +254,45 @@ PKGMGR 1.0.0 unifies repository management, build tooling, release automation an
## [0.7.1] - 2025-12-09 ## [0.7.1] - 2025-12-09
* Fix floating 'latest' tag logic: dereference annotated target (vX.Y.Z^{}), add tag message to avoid Git errors, ensure best-effort update without blocking releases, and update unit tests (see ChatGPT conversation: https://chatgpt.com/share/69383024-efa4-800f-a875-129b81fa40ff). * Fix floating 'latest' tag logic
* dereference annotated target (vX.Y.Z^{})
* add tag message to avoid Git errors
* ensure best-effort update without blocking releases
## [0.7.0] - 2025-12-09 ## [0.7.0] - 2025-12-09
* Add Git helpers for branch sync and floating 'latest' tag in the release workflow, ensure main/master are updated from origin before tagging, and extend unit/e2e tests including 'pkgmgr release --help' coverage (see ChatGPT conversation: https://chatgpt.com/share/69383024-efa4-800f-a875-129b81fa40ff) * Add Git helpers for branch sync and floating 'latest' tag in the release workflow
* ensure main/master are updated from origin before tagging
## [0.6.0] - 2025-12-09 ## [0.6.0] - 2025-12-09
* Expose DISTROS and BASE_IMAGE_* variables as exported Makefile environment variables so all build and test commands can consume them dynamically. By exporting these values, every Make target (e.g., build, build-no-cache, build-missing, test-container, test-unit, test-e2e) and every delegated script in scripts/build/ and scripts/test/ now receives a consistent view of the supported distributions and their base container images. This change removes duplicated definitions across scripts, ensures reproducible builds, and allows build tooling to react automatically when new distros or base images are added to the Makefile. * Consistent view of the supported distributions and their base container images.
## [0.5.1] - 2025-12-09 ## [0.5.1] - 2025-12-09
* Refine pkgmgr release CLI close wiring and integration tests for --close flag (ChatGPT: https://chatgpt.com/share/69376b4e-8440-800f-9d06-535ec1d7a40e) * Refine pkgmgr release CLI close wiring and integration tests for --close flag
## [0.5.0] - 2025-12-09 ## [0.5.0] - 2025-12-09
* Add pkgmgr branch close subcommand, extend CLI parser wiring, and add unit tests for branch handling and version version-selection logic (see ChatGPT conversation: https://chatgpt.com/share/693762a3-9ea8-800f-a640-bc78170953d1) * Add pkgmgr branch close subcommand, extend CLI parser wiring
## [0.4.3] - 2025-12-09 ## [0.4.3] - 2025-12-09
* Implement current-directory repository selection for release and proxy commands, unify selection semantics across CLI layers, extend release workflow with --close, integrate branch closing logic, fix wiring for get_repo_identifier/get_repo_dir, update packaging files (PKGBUILD, spec, flake.nix, pyproject), and add comprehensive unit/e2e tests for release and branch commands (see ChatGPT conversation: https://chatgpt.com/share/69375cfe-9e00-800f-bd65-1bd5937e1696) * Implement current-directory repository selection for release and proxy commands, unify selection semantics across CLI layers, extend release workflow with --close, integrate branch closing logic, fix wiring for get_repo_identifier/get_repo_dir, update packaging files (PKGBUILD, spec, flake.nix, pyproject)
## [0.4.2] - 2025-12-09 ## [0.4.2] - 2025-12-09
* Wire pkgmgr release CLI to new helper and add unit tests (see ChatGPT conversation: https://chatgpt.com/share/69374f09-c760-800f-92e4-5b44a4510b62) * Wire pkgmgr release CLI to new helpe
## [0.4.1] - 2025-12-08 ## [0.4.1] - 2025-12-08
* Add branch close subcommand and integrate release close/editor flow (ChatGPT: https://chatgpt.com/share/69374f09-c760-800f-92e4-5b44a4510b62) * Add branch close subcommand and integrate release close/editor flow
## [0.4.0] - 2025-12-08 ## [0.4.0] - 2025-12-08
* Add branch closing helper and --close flag to release command, including CLI wiring and tests (see https://chatgpt.com/share/69374aec-74ec-800f-bde3-5d91dfdb9b91) * Add branch closing helper and --close flag to release command
## [0.3.0] - 2025-12-08 ## [0.3.0] - 2025-12-08
@@ -299,13 +303,10 @@ PKGMGR 1.0.0 unifies repository management, build tooling, release automation an
- New config update logic + default YAML sync - New config update logic + default YAML sync
- Improved proxy command handling - Improved proxy command handling
- Full CLI routing refactor - Full CLI routing refactor
- Expanded E2E tests for list, proxy, and selection logic
Konversation: https://chatgpt.com/share/693745c3-b8d8-800f-aa29-c8481a2ffae1
## [0.2.0] - 2025-12-08 ## [0.2.0] - 2025-12-08
* Add preview-first release workflow and extended packaging support (see ChatGPT conversation: https://chatgpt.com/share/693722b4-af9c-800f-bccc-8a4036e99630) * Add preview-first release workflow and extended packaging support
## [0.1.0] - 2025-12-08 ## [0.1.0] - 2025-12-08
@@ -314,5 +315,4 @@ Konversation: https://chatgpt.com/share/693745c3-b8d8-800f-aa29-c8481a2ffae1
## [0.1.0] - 2025-12-08 ## [0.1.0] - 2025-12-08
* Implement unified release helper with preview mode, multi-packaging version bumps, and new integration/unit tests (see ChatGPT conversation 2025-12-08: https://chatgpt.com/share/693722b4-af9c-800f-bccc-8a4036e99630) * Implement unified release helper with preview mode, multi-packaging version bumps

View File

@@ -30,6 +30,7 @@ export BASE_IMAGE_CENTOS
# PYthon Unittest Pattern # PYthon Unittest Pattern
TEST_PATTERN := test_*.py TEST_PATTERN := test_*.py
export TEST_PATTERN export TEST_PATTERN
export PYTHONPATH := src
# ------------------------------------------------------------ # ------------------------------------------------------------
# System install # System install
@@ -45,7 +46,7 @@ install:
# Default: keep current auto-detection behavior # Default: keep current auto-detection behavior
setup: setup-nix setup-venv setup: setup-nix setup-venv
# Explicit: developer setup (Python venv + shell RC + main.py install) # Explicit: developer setup (Python venv + shell RC + install)
setup-venv: setup-nix setup-venv: setup-nix
@bash scripts/setup/venv.sh @bash scripts/setup/venv.sh

167
README.md
View File

@@ -25,52 +25,37 @@ together into repeatable development workflows.
Traditional distro package managers like `apt`, `pacman` or `dnf` focus on a Traditional distro package managers like `apt`, `pacman` or `dnf` focus on a
single operating system. PKGMGR instead focuses on **your repositories and single operating system. PKGMGR instead focuses on **your repositories and
development lifecycle**: development lifecycle**. It provides one configuration for all repositories,
one unified CLI to interact with them, and a Nix-based foundation that keeps
tooling reproducible across distributions.
* one configuration for all your repos, Native package managers are still used where they make sense. PKGMGR coordinates
* one CLI to interact with them, the surrounding development, build and release workflows in a consistent way.
* one Nix-based layer to keep tooling reproducible across distros.
You keep using your native package manager where it makes sense PKGMGR In addition, PKGMGR provides Docker images that can serve as a **reproducible
coordinates the *development and release flow* around it. system baseline**. These images bundle the complete PKGMGR toolchain and are
designed to be reused as a stable execution environment across machines,
pipelines and teams. This approach is specifically used within
[**Infinito.Nexus**](https://s.infinito.nexus/code) to make complex systems
distribution-independent while remaining fully reproducible.
--- ---
## Features 🚀 ## Features 🚀
### Multi-distro development & packaging PKGMGR enables multi-distro development and packaging by managing multiple
repositories from a single configuration file. It drives complete release
pipelines across Linux distributions using Nix flakes, Python build metadata,
native OS packages such as Arch, Debian and RPM formats, and additional ecosystem
integrations like Ansible.
* Manage **many repositories at once** from a single `config/config.yaml`. All functionality is exposed through a unified `pkgmgr` command-line interface
* Drive full **release pipelines** across Linux distributions using: that works identically on every supported distribution. It combines repository
management, Git operations, Docker and Compose orchestration, as well as
versioning, release and changelog workflows. Many commands support a preview
mode, allowing you to inspect the underlying actions before they are executed.
* Nix flakes (`flake.nix`) ---
* PyPI style builds (`pyproject.toml`)
* OS packages (PKGBUILD, Debian control/changelog, RPM spec)
* Ansible Galaxy metadata and more.
### Rich CLI for daily work
All commands are exposed via the `pkgmgr` CLI and are available on every distro:
* **Repository management**
* `clone`, `update`, `install`, `delete`, `deinstall`, `path`, `list`, `config`
* **Git proxies**
* `pull`, `push`, `status`, `diff`, `add`, `show`, `checkout`,
`reset`, `revert`, `rebase`, `commit`, `branch`
* **Docker & Compose orchestration**
* `build`, `up`, `down`, `exec`, `ps`, `start`, `stop`, `restart`
* **Release toolchain**
* `version`, `release`, `changelog`, `make`
* **Mirror & workflow helpers**
* `mirror` (list/diff/merge/setup), `shell`, `terminal`, `code`, `explore`
Many of these commands support `--preview` mode so you can inspect the
underlying Git or Docker calls without executing them.
### Full development workflows ### Full development workflows
@@ -83,10 +68,6 @@ versioning features it can drive **end-to-end workflows**:
4. Build distro-specific packages. 4. Build distro-specific packages.
5. Keep all mirrors and working copies in sync. 5. Keep all mirrors and working copies in sync.
The extensive E2E tests (`tests/e2e/`) and GitHub Actions workflows (including
“virgin user” and “virgin root” Arch tests) validate these flows across
different Linux environments.
--- ---
## Architecture & Setup Map 🗺️ ## Architecture & Setup Map 🗺️
@@ -99,25 +80,26 @@ The following diagram gives a full overview of:
![PKGMGR Architecture](assets/map.png) ![PKGMGR Architecture](assets/map.png)
**Diagram status:** 12 December 2025 **Diagram status:** 12 December 2025
**Always-up-to-date version:** [https://s.veen.world/pkgmgrmp](https://s.veen.world/pkgmgrmp) **Always-up-to-date version:** [https://s.veen.world/pkgmgrmp](https://s.veen.world/pkgmgrmp)
--- ---
Perfekt, dann hier die **noch kompaktere und korrekt differenzierte Version**, die **nur** zwischen
**`make setup`** und **`make setup-venv`** unterscheidet und exakt deinem Verhalten entspricht.
README-ready, ohne Over-Engineering.
---
## Installation ⚙️ ## Installation ⚙️
PKGMGR can be installed using `make`. PKGMGR can be installed using `make`.
The setup mode defines **which runtime layers are prepared**. The setup mode defines **which runtime layers are prepared**.
--- ---
### Download
```bash
git clone https://github.com/kevinveenbirkenbach/package-manager.git
cd package-manager
```
### Dependency installation (optional) ### Dependency installation (optional)
System dependencies required **before running any *make* commands** are installed via: System dependencies required **before running any *make* commands** are installed via:
@@ -128,8 +110,13 @@ scripts/installation/dependencies.sh
The script detects and normalizes the OS and installs the required **system-level dependencies** accordingly. The script detects and normalizes the OS and installs the required **system-level dependencies** accordingly.
### Install
--- ```bash
git clone https://github.com/kevinveenbirkenbach/package-manager.git
cd package-manager
make install
```
### Setup modes ### Setup modes
@@ -138,17 +125,8 @@ The script detects and normalizes the OS and installs the required **system-leve
| **make setup** | Python venv **and** Nix | Full development & CI | | **make setup** | Python venv **and** Nix | Full development & CI |
| **make setup-venv** | Python venv only | Local user setup | | **make setup-venv** | Python venv only | Local user setup |
---
### Install & setup ##### Full setup (venv + Nix)
```bash
git clone https://github.com/kevinveenbirkenbach/package-manager.git
cd package-manager
make install
```
#### Full setup (venv + Nix)
```bash ```bash
make setup make setup
@@ -156,7 +134,7 @@ make setup
Use this for CI, servers, containers and full development workflows. Use this for CI, servers, containers and full development workflows.
#### Venv-only setup ##### Venv-only setup
```bash ```bash
make setup-venv make setup-venv
@@ -167,38 +145,77 @@ Use this if you want PKGMGR isolated without Nix integration.
--- ---
## Run without installation (Nix) Alles klar 🙂
Hier ist der **RUN-Abschnitt ohne Gedankenstriche**, klar nach **Nix, Docker und venv** getrennt:
Run PKGMGR directly via Nix Flakes. ---
## Run PKGMGR 🧰
PKGMGR can be executed in different environments.
All modes expose the same CLI and commands.
---
### Run via Nix (no installation)
```bash ```bash
nix run github:kevinveenbirkenbach/package-manager#pkgmgr -- --help nix run github:kevinveenbirkenbach/package-manager#pkgmgr -- --help
``` ```
Example: ---
```bash ### Run via Docker 🐳
nix run github:kevinveenbirkenbach/package-manager#pkgmgr -- version pkgmgr
```
Notes: PKGMGR can be executed **inside Docker containers** for CI, testing and isolated
workflows.
---
* full flake URL required #### Container types
* `--` separates Nix and PKGMGR arguments
* can be used alongside any setup mode Two container types are available.
| Image type | Contains | Typical use |
| ---------- | ----------------------------- | ----------------------- |
| **Virgin** | Base OS + system dependencies | Clean test environments |
| **Stable** | PKGMGR + Nix (flakes enabled) | Ready-to-use workflows |
Example images:
* Virgin: `pkgmgr-arch-virgin`
* Stable: `ghcr.io/kevinveenbirkenbach/pkgmgr:stable`
Use **virgin images** for isolated test runs,
use the **stable image** for fast, reproducible execution.
--- ---
## Usage 🧰 #### Run examples
After installation, the main entry point is: ```bash
docker run --rm -it \
-v "$PWD":/src \
-w /src \
ghcr.io/kevinveenbirkenbach/pkgmgr:stable \
pkgmgr --help
```
---
### Run via virtual environment (venv)
After activating the venv:
```bash ```bash
pkgmgr --help pkgmgr --help
``` ```
This prints a list of all available subcommands. ---
The help for each command is available via:
This allows you to choose between zero install execution using Nix, fully prebuilt
Docker environments or local isolated venv setups with identical command behavior.
--- ---

View File

@@ -36,7 +36,7 @@
rec { rec {
pkgmgr = pyPkgs.buildPythonApplication { pkgmgr = pyPkgs.buildPythonApplication {
pname = "package-manager"; pname = "package-manager";
version = "1.4.0"; version = "1.4.1";
# Use the git repo as source # Use the git repo as source
src = ./.; src = ./.;

14
main.py
View File

@@ -1,14 +0,0 @@
#!/usr/bin/env python3
import sys
from pathlib import Path
# Ensure local src/ overrides installed package
ROOT = Path(__file__).resolve().parent
SRC = ROOT / "src"
if SRC.is_dir():
sys.path.insert(0, str(SRC))
from pkgmgr.cli import main
if __name__ == "__main__":
main()

View File

@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "package-manager" name = "package-manager"
version = "1.4.0" version = "1.4.1"
description = "Kevin's package-manager tool (pkgmgr)" description = "Kevin's package-manager tool (pkgmgr)"
readme = "README.md" readme = "README.md"
requires-python = ">=3.9" requires-python = ">=3.9"

View File

@@ -1,9 +1,9 @@
# ------------------------------------------------------------ # ------------------------------------------------------------
# Nix shell mode: do not touch venv, only run main.py install # Nix shell mode: do not touch venv, only run install
# ------------------------------------------------------------ # ------------------------------------------------------------
echo "[setup] Nix mode enabled (NIX_ENABLED=1)." echo "[setup] Nix mode enabled (NIX_ENABLED=1)."
echo "[setup] Skipping virtualenv creation and dependency installation." echo "[setup] Skipping virtualenv creation and dependency installation."
echo "[setup] Running main.py install via system python3..." echo "[setup] Running install via system python3..."
python3 main.py install python3 -m pkgmgr install
echo "[setup] Setup finished (Nix mode)." echo "[setup] Setup finished (Nix mode)."

View File

@@ -15,9 +15,6 @@ RC_LINE='if [ -d "${HOME}/.venvs/pkgmgr" ]; then . "${HOME}/.venvs/pkgmgr/bin/ac
echo "[setup] Running in normal user mode (developer setup)." echo "[setup] Running in normal user mode (developer setup)."
echo "[setup] Ensuring main.py is executable..."
chmod +x main.py || true
echo "[setup] Ensuring global virtualenv root: ${HOME}/.venvs" echo "[setup] Ensuring global virtualenv root: ${HOME}/.venvs"
mkdir -p "${HOME}/.venvs" mkdir -p "${HOME}/.venvs"
@@ -90,8 +87,8 @@ for rc in "${HOME}/.bashrc" "${HOME}/.zshrc"; do
fi fi
done done
echo "[setup] Running main.py install via venv Python..." echo "[setup] Running install via venv Python..."
"${VENV_DIR}/bin/python" main.py install "${VENV_DIR}/bin/python" -m pkgmgr install
echo echo
echo "[setup] Developer setup complete." echo "[setup] Developer setup complete."

5
src/pkgmgr/__main__.py Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env python3
from pkgmgr.cli import main
if __name__ == "__main__":
main()

View File

@@ -27,7 +27,7 @@ class TestIntegrationBranchCommands(unittest.TestCase):
try: try:
# argv[0] is the program name; the rest are CLI arguments. # argv[0] is the program name; the rest are CLI arguments.
sys.argv = ["pkgmgr"] + list(extra_args) sys.argv = ["pkgmgr"] + list(extra_args)
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
finally: finally:
sys.argv = original_argv sys.argv = original_argv

View File

@@ -24,7 +24,7 @@ def _run_pkgmgr_help(argv_tail: list[str]) -> str:
try: try:
with redirect_stdout(buffer), redirect_stderr(buffer): with redirect_stdout(buffer), redirect_stderr(buffer):
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else None code = exc.code if isinstance(exc.code, int) else None
if code not in (0, None): if code not in (0, None):

View File

@@ -53,7 +53,7 @@ class TestIntegrationChangelogCommands(unittest.TestCase):
sys.argv = ["pkgmgr", "changelog"] + list(extra_args) sys.argv = ["pkgmgr", "changelog"] + list(extra_args)
try: try:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else str(exc.code) code = exc.code if isinstance(exc.code, int) else str(exc.code)
if code != 0: if code != 0:

View File

@@ -47,7 +47,7 @@ class TestIntegrationCloneAllHttps(unittest.TestCase):
try: try:
# Execute main.py as if it was called from CLI. # Execute main.py as if it was called from CLI.
# This will run the full clone pipeline inside the container. # This will run the full clone pipeline inside the container.
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
# Determine the exit code (int or string) # Determine the exit code (int or string)
exit_code = exc.code exit_code = exc.code

View File

@@ -34,7 +34,7 @@ def _run_pkgmgr_config(extra_args: list[str]) -> None:
sys.argv = ["pkgmgr"] + extra_args sys.argv = ["pkgmgr"] + extra_args
try: try:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else str(exc.code) code = exc.code if isinstance(exc.code, int) else str(exc.code)
if code != 0: if code != 0:

View File

@@ -139,7 +139,7 @@ class TestIntegrationInstalPKGMGRShallow(unittest.TestCase):
] ]
# Execute installation via main.py # Execute installation via main.py
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
# Debug: interactive shell test # Debug: interactive shell test
pkgmgr_help_debug() pkgmgr_help_debug()

View File

@@ -27,7 +27,7 @@ class TestIntegrationListCommands(unittest.TestCase):
sys.argv = ["pkgmgr"] + args sys.argv = ["pkgmgr"] + args
try: try:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else str(exc.code) code = exc.code if isinstance(exc.code, int) else str(exc.code)
if code != 0: if code != 0:

View File

@@ -44,7 +44,7 @@ class TestIntegrationMakeCommands(unittest.TestCase):
sys.argv = ["pkgmgr"] + extra_args sys.argv = ["pkgmgr"] + extra_args
try: try:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else str(exc.code) code = exc.code if isinstance(exc.code, int) else str(exc.code)
if code != 0: if code != 0:

View File

@@ -50,7 +50,7 @@ class TestIntegrationMirrorCommands(unittest.TestCase):
try: try:
with redirect_stdout(buffer), redirect_stderr(buffer): with redirect_stdout(buffer), redirect_stderr(buffer):
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else None code = exc.code if isinstance(exc.code, int) else None
if code not in (0, None): if code not in (0, None):

View File

@@ -50,7 +50,7 @@ class TestPathCommandsE2E(unittest.TestCase):
try: try:
# Capture stdout while running the CLI entry point. # Capture stdout while running the CLI entry point.
with redirect_stdout(buffer): with redirect_stdout(buffer):
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
# Determine the exit code (int or string) # Determine the exit code (int or string)
exit_code = exc.code exit_code = exc.code

View File

@@ -27,7 +27,7 @@ class TestIntegrationProxyCommands(unittest.TestCase):
sys.argv = ["pkgmgr"] + args sys.argv = ["pkgmgr"] + args
try: try:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else str(exc.code) code = exc.code if isinstance(exc.code, int) else str(exc.code)
if code != 0: if code != 0:

View File

@@ -44,7 +44,7 @@ class TestIntegrationReleaseCommand(unittest.TestCase):
try: try:
# argv[0] is the program name; the rest are CLI arguments. # argv[0] is the program name; the rest are CLI arguments.
sys.argv = ["pkgmgr"] + list(extra_args) sys.argv = ["pkgmgr"] + list(extra_args)
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
finally: finally:
sys.argv = original_argv sys.argv = original_argv
@@ -152,7 +152,7 @@ class TestIntegrationReleaseCommand(unittest.TestCase):
# argparse will call sys.exit(), so we expect a SystemExit here. # argparse will call sys.exit(), so we expect a SystemExit here.
with contextlib.redirect_stdout(buf), contextlib.redirect_stderr(buf): with contextlib.redirect_stdout(buf), contextlib.redirect_stderr(buf):
with self.assertRaises(SystemExit) as cm: with self.assertRaises(SystemExit) as cm:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
finally: finally:
sys.argv = original_argv sys.argv = original_argv

View File

@@ -55,7 +55,7 @@ class TestIntegrationToolsCommands(unittest.TestCase):
sys.argv = ["pkgmgr"] + extra_args sys.argv = ["pkgmgr"] + extra_args
try: try:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else str(exc.code) code = exc.code if isinstance(exc.code, int) else str(exc.code)
if code != 0: if code != 0:

View File

@@ -18,14 +18,6 @@ import sys
import unittest import unittest
from typing import List from typing import List
# Resolve project root (the repo where main.py lives, e.g. /src)
PROJECT_ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
MAIN_PATH = os.path.join(PROJECT_ROOT, "main.py")
def _run_main(argv: List[str]) -> None: def _run_main(argv: List[str]) -> None:
""" """
Helper to run main.py with the given argv. Helper to run main.py with the given argv.
@@ -40,7 +32,7 @@ def _run_main(argv: List[str]) -> None:
try: try:
sys.argv = ["pkgmgr"] + argv sys.argv = ["pkgmgr"] + argv
try: try:
runpy.run_path(MAIN_PATH, run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: # argparse uses this for --help except SystemExit as exc: # argparse uses this for --help
# SystemExit.code can be int, str or None; for our purposes: # SystemExit.code can be int, str or None; for our purposes:
code = exc.code code = exc.code

View File

@@ -130,7 +130,7 @@ class TestIntegrationVersionCommands(unittest.TestCase):
sys.argv = ["pkgmgr", "version"] + extra_args sys.argv = ["pkgmgr", "version"] + extra_args
try: try:
runpy.run_module("main", run_name="__main__") runpy.run_module("pkgmgr", run_name="__main__")
except SystemExit as exc: except SystemExit as exc:
code = exc.code if isinstance(exc.code, int) else str(exc.code) code = exc.code if isinstance(exc.code, int) else str(exc.code)
if code != 0: if code != 0: