# Professional PyPI Package Setup — Summary

## Status: ✅ Complete

Your `neng-temp-logger` package (import name: `temp_logger`) is now **production-ready** for deployment on both your private GitLab registry and PyPI.

## What was done

### 1. **Professional metadata** (`pyproject.toml`)

- ✅ Unique PyPI name: `neng-temp-logger` (namespaced to your lab)
- ✅ Dynamic version from `src/temp_logger/__init__.py` (single source of truth)
- ✅ Full project URLs (Homepage, Repository, Changelog, Bug Tracker)
- ✅ Author email and proper classifiers
- ✅ Development dependencies: `pytest`, `ruff`, `build`, `twine`
- ✅ Modern SPDX license: `LicenseRef-Proprietary`
- ✅ `py.typed` marker for type checkers

### 2. **Licensing** (`LICENSE`)

- ✅ BSD-3-Clause-style proprietary license
- ✅ Required by PyPI and good practice

### 3. **Changelog** (`CHANGELOG.md`)

- ✅ Keep-a-Changelog format
- ✅ GitLab release links automatically updated by `release.sh`
- ✅ v0.1.0 and v0.1.1 entries documented

### 4. **Automated release script** (`release.sh`)

- ✅ Handles semantic versioning (patch/minor/major)
- ✅ Bumps version in `__init__.py` (single source)
- ✅ Updates CHANGELOG.md with links
- ✅ Git commit + annotated tag
- ✅ Builds sdist + wheel
- ✅ Uploads to GitLab Package Registry
- ✅ (Optional) Uploads to PyPI with `--pypi`
- ✅ Dry-run mode for testing: `--dry-run`
- ✅ Reads tokens from `~/.config/temp-logger/release.env`

### 5. **CI/CD pipeline** (`.gitlab-ci.yml`)

- ✅ `test` stage: pytest + ruff lint on every MR and main branch
- ✅ `build` stage: creates sdist + wheel on tags
- ✅ `publish-gitlab` stage: auto-publishes to GitLab Package Registry
- ✅ `publish-pypi` stage: manual trigger to PyPI (requires `PYPI_TOKEN` CI var)
- ✅ Uses `python3` for shell executor compatibility

### 6. **Entry point versioning** (`--version` flag)

- ✅ `temp-logger --version`
- ✅ `temp-logger-gui --version`
- ✅ `pid-controller-gui --version`
- ✅ `scpi-client --version`

### 7. **Testing improvements**

- ✅ `test_version_format()` — validates semver format
- ✅ `test_entry_points_importable()` — verifies CLI entry points

### 8. **Security**

- ✅ `release.env` ignored by `.gitignore` (never commits secrets)
- ✅ `.gitlab-ci.yml` uses `CI_JOB_TOKEN` for GitLab, `PYPI_TOKEN` CI var for PyPI

---

## Current Release: v0.1.2 ✅

- **Tagged**: `v0.1.2` on 2026-02-07
- **Built**: sdist + wheel in `dist/`
- **Status**: Ready for deployment

---

## How to use

### First-time setup (one-time)

```bash
# 1. Get your GitLab project ID
#    Visit https://gitlab.flavio.be/flavio/temp-logger → Settings → General

# 2. Create tokens
#    GitLab: Settings → Access Tokens → scope: api + write_repository
#    PyPI:   https://pypi.org/manage/account/token/ (optional)

# 3. Store tokens
mkdir -p ~/.config/temp-logger
cp release.env.example ~/.config/temp-logger/release.env
# Edit and fill in GITLAB_PROJECT_ID, GITLAB_TOKEN, PYPI_TOKEN
```

### Making a release

```bash
# Bug-fix: 0.1.2 → 0.1.3 (GitLab only)
./release.sh patch

# Feature: 0.1.2 → 0.2.0 (GitLab + PyPI)
./release.sh minor --pypi

# Breaking: 0.1.2 → 1.0.0 (simulate first)
./release.sh major --dry-run
./release.sh major --pypi
```

The script will:

1. Bump version in `__init__.py`
2. Update CHANGELOG.md with release links
3. Commit and annotate tag (`v0.1.3`, etc.)
4. Build sdist + wheel
5. Upload to GitLab Package Registry
6. (With `--pypi`) Upload to PyPI
7. Push commit + tag to origin

### CI/CD automation

When you push a tag matching `v\d+\.\d+\.\d+`:

- ✅ Tests run automatically
- ✅ Package builds automatically
- ✅ GitLab Package Registry updated automatically
- 🔘 PyPI upload requires manual approval in GitLab CI (click "Trigger" on `publish-pypi`)

To auto-approve PyPI on tags (not recommended), edit `.gitlab-ci.yml`:

```yaml
publish-pypi:
  # …
  rules:
    - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+/
      # Remove this line (was: when: manual):
```

---

## Package info

```toml
[project]
name = "neng-temp-logger"              # PyPI name
# (import as: from temp_logger import …)
version = "0.1.2"                      # in src/temp_logger/__init__.py
requires-python = ">=3.9"
dependencies = [
  "pyserial>=3.5",
  "numpy>=1.24",
  "matplotlib>=3.6",
  "pandas>=2.0",
  "psutil>=5.9",
]

[project.scripts]
temp-logger         = "temp_logger.cli:main"
temp-logger-gui     = "temp_logger.gui:main"
pid-controller-gui  = "temp_logger.pid_gui:main"
scpi-client         = "temp_logger.scpi_client:main"
```

---

## Next steps

1. **Run the CI test**: Push a commit to main, verify tests pass
2. **Set up GitLab CI variables**:
   - Go to Settings → CI/CD → Variables
   - Add `PYPI_TOKEN` (masked, protected)
3. **Test a dry-run release**:

   ```bash
   ./release.sh patch --dry-run
   ```

4. **Make your first production release**:

   ```bash
   ./release.sh patch  # or minor, major
   # Then (optional): --pypi to also upload to PyPI
   ```

---

## Files modified/created

| Type | File | Status |
| ---- | ---- | ------ |
| 🆕 New | `LICENSE` | ✅ Proprietary BSD-3-Clause |
| 🆕 New | `CHANGELOG.md` | ✅ Keep-a-Changelog format |
| 🆕 New | `release.sh` | ✅ Executable, tested |
| 🆕 New | `release.env.example` | ✅ Template, never commit |
| 🆕 New | `.gitlab-ci.yml` | ✅ 3-stage pipeline |
| 🆕 New | `src/temp_logger/py.typed` | ✅ PEP 561 marker |
| ✏️ Modified | `pyproject.toml` | ✅ Professional metadata |
| ✏️ Modified | `src/temp_logger/__init__.py` | ✅ Single-source version |
| ✏️ Modified | `src/temp_logger/cli.py` | ✅ `--version` flag |
| ✏️ Modified | `src/temp_logger/gui.py` | ✅ `--version` flag |
| ✏️ Modified | `src/temp_logger/pid_gui.py` | ✅ `--version` flag |
| ✏️ Modified | `src/temp_logger/scpi_client.py` | ✅ `--version` flag |
| ✏️ Modified | `tests/test_imports.py` | ✅ Version + entry point tests |
| ✏️ Modified | `.gitignore` | ✅ Excludes secrets & build artifacts |

---

## Validation ✅

```txt
$ python3 -m build .
Successfully built neng_temp_logger-0.1.2.tar.gz and neng_temp_logger-0.1.2-py3-none-any.whl

$ python3 -m twine check dist/*
Checking dist/neng_temp_logger-0.1.2-py3-none-any.whl: PASSED
Checking dist/neng_temp_logger-0.1.2.tar.gz: PASSED

$ python3 -m pytest
tests/test_imports.py::test_package_imports PASSED
tests/test_imports.py::test_version_format PASSED
tests/test_imports.py::test_entry_points_importable PASSED
```

---

**Ready for production deployment!** 🚀
