mycom-app 0.1.0__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.
@@ -0,0 +1,4 @@
1
+ # Everyone may change the package code; changes to the CI configuration need a
2
+ # release approver. Paired with "Require review from Code Owners" on main.
3
+
4
+ /.github/workflows/ @mycom-lab/mycom-approvers
@@ -0,0 +1,50 @@
1
+ name: CI
2
+
3
+ # Read-only checks: this workflow only checks out code and runs the test suite.
4
+ # It publishes and commits nothing, so it needs no write scopes.
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ pull_request:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ concurrency:
15
+ group: ci-${{ github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ test:
20
+ name: Test (python ${{ matrix.python }})
21
+ runs-on: ubuntu-latest
22
+ timeout-minutes: 10
23
+ strategy:
24
+ fail-fast: false
25
+ matrix:
26
+ python: ["3.10", "3.11", "3.12", "3.13"]
27
+ steps:
28
+ - name: Checkout
29
+ uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
30
+ with:
31
+ persist-credentials: false
32
+
33
+ - name: Setup Python
34
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
35
+ with:
36
+ python-version: ${{ matrix.python }}
37
+
38
+ - name: Install
39
+ run: |
40
+ set -euo pipefail
41
+ python -m pip install --quiet --disable-pip-version-check ".[test]"
42
+
43
+ - name: Test
44
+ run: python -m pytest -q
45
+
46
+ - name: Build the wheel to prove packaging works
47
+ run: |
48
+ set -euo pipefail
49
+ python -m pip install --quiet --disable-pip-version-check build
50
+ python -m build --outdir dist
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .pytest_cache/
7
+ .venv/
@@ -0,0 +1,19 @@
1
+ # Base image pinned by digest (linux/amd64), not by tag: the pipeline builds
2
+ # amd64 only, so the digest is the same thing a tag pull would resolve to.
3
+ FROM python:3.12-slim@sha256:2b4f19dae3a777dfc3b76730bda1e82e1f66ab2a2686fa93ca78edbfb4f04ffe
4
+
5
+ LABEL org.opencontainers.image.title="mycom-app" \
6
+ org.opencontainers.image.description="Lab package exercised by a build and publish pipeline"
7
+
8
+ WORKDIR /app
9
+
10
+ COPY pyproject.toml README.md ./
11
+ COPY src ./src
12
+
13
+ RUN pip install --no-cache-dir --no-compile .
14
+
15
+ # Run unprivileged: the image only needs to print a greeting.
16
+ USER 65532:65532
17
+
18
+ ENTRYPOINT ["mycom-app"]
19
+ CMD ["greet"]
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.3
2
+ Name: mycom-app
3
+ Version: 0.1.0
4
+ Summary: Lab package used to exercise a build-and-publish pipeline end to end.
5
+ Author: mycom lab
6
+ License: MIT
7
+ Keywords: lab,release-pipeline
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Requires-Python: >=3.10
11
+ Provides-Extra: test
12
+ Requires-Dist: pytest>=8.0; extra == 'test'
13
+ Description-Content-Type: text/markdown
14
+
15
+ # mycom-app
16
+
17
+ Small, self-contained Python package used as the *source* side of a two-repository
18
+ release lab.
19
+
20
+ - The package itself does one harmless thing: a CLI with `greet` and `version`.
21
+ - It exists so that a separate pipeline repository has something real to build,
22
+ test, version-stamp, containerise and publish.
23
+
24
+ ## Layout
25
+
26
+ ```
27
+ pyproject.toml packaging metadata (the pipeline stamps `version`)
28
+ src/mycom_app/ the package
29
+ tests/ pytest suite
30
+ Dockerfile image used by the pipeline's container leg
31
+ ```
32
+
33
+ ## Local use
34
+
35
+ ```bash
36
+ python -m pip install -e '.[test]'
37
+ pytest
38
+ mycom-app greet --name lab
39
+ mycom-app version
40
+ ```
41
+
42
+ ## Notes for the pipeline
43
+
44
+ - The version lives only in `pyproject.toml`. The pipeline rewrites that field
45
+ before building; the package reads the installed distribution metadata, so the
46
+ two can never disagree.
47
+ - Everything here is throwaway test code. Nothing in this repository is intended
48
+ for real consumption.
@@ -0,0 +1,34 @@
1
+ # mycom-app
2
+
3
+ Small, self-contained Python package used as the *source* side of a two-repository
4
+ release lab.
5
+
6
+ - The package itself does one harmless thing: a CLI with `greet` and `version`.
7
+ - It exists so that a separate pipeline repository has something real to build,
8
+ test, version-stamp, containerise and publish.
9
+
10
+ ## Layout
11
+
12
+ ```
13
+ pyproject.toml packaging metadata (the pipeline stamps `version`)
14
+ src/mycom_app/ the package
15
+ tests/ pytest suite
16
+ Dockerfile image used by the pipeline's container leg
17
+ ```
18
+
19
+ ## Local use
20
+
21
+ ```bash
22
+ python -m pip install -e '.[test]'
23
+ pytest
24
+ mycom-app greet --name lab
25
+ mycom-app version
26
+ ```
27
+
28
+ ## Notes for the pipeline
29
+
30
+ - The version lives only in `pyproject.toml`. The pipeline rewrites that field
31
+ before building; the package reads the installed distribution metadata, so the
32
+ two can never disagree.
33
+ - Everything here is throwaway test code. Nothing in this repository is intended
34
+ for real consumption.
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ # Upper bound on purpose: newer hatchling releases emit Metadata-Version 2.5,
3
+ # which the publish action's bundled tooling rejects ("'2.5' is not a valid
4
+ # metadata version"). 1.26 emits 2.3.
5
+ requires = ["hatchling>=1.25,<1.27"]
6
+ build-backend = "hatchling.build"
7
+
8
+ [project]
9
+ name = "mycom-app"
10
+ version = "0.1.0"
11
+ description = "Lab package used to exercise a build-and-publish pipeline end to end."
12
+ readme = "README.md"
13
+ requires-python = ">=3.10"
14
+ license = { text = "MIT" }
15
+ authors = [{ name = "mycom lab" }]
16
+ keywords = ["lab", "release-pipeline"]
17
+ classifiers = [
18
+ "Programming Language :: Python :: 3",
19
+ "License :: OSI Approved :: MIT License",
20
+ ]
21
+
22
+ [project.scripts]
23
+ mycom-app = "mycom_app.cli:main"
24
+
25
+ [project.optional-dependencies]
26
+ test = ["pytest>=8.0"]
27
+
28
+ [tool.hatch.build.targets.wheel]
29
+ packages = ["src/mycom_app"]
30
+
31
+ [tool.pytest.ini_options]
32
+ testpaths = ["tests"]
33
+ addopts = "-q"
@@ -0,0 +1,21 @@
1
+ """Lab package.
2
+
3
+ The version is read from installed distribution metadata so that stamping the
4
+ version into ``pyproject.toml`` at build time is the single source of truth.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from importlib.metadata import PackageNotFoundError, version
10
+
11
+ DISTRIBUTION = "mycom-app"
12
+
13
+
14
+ def __version__() -> str:
15
+ try:
16
+ return version(DISTRIBUTION)
17
+ except PackageNotFoundError: # running from a source checkout
18
+ return "0.0.0+unknown"
19
+
20
+
21
+ __all__ = ["DISTRIBUTION", "__version__"]
@@ -0,0 +1,40 @@
1
+ """Tiny CLI used to give the pipeline something real to build, test and ship."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ import sys
8
+
9
+ from mycom_app import __version__
10
+
11
+
12
+ def build_parser() -> argparse.ArgumentParser:
13
+ parser = argparse.ArgumentParser(prog="mycom-app", description="Lab CLI")
14
+ sub = parser.add_subparsers(dest="command", required=True)
15
+
16
+ greet = sub.add_parser("greet", help="print a greeting")
17
+ greet.add_argument("--name", default="world")
18
+
19
+ sub.add_parser("version", help="print the installed version")
20
+
21
+ return parser
22
+
23
+
24
+ def run(argv: list[str] | None = None) -> int:
25
+ args = build_parser().parse_args(argv)
26
+ if args.command == "version":
27
+ print(json.dumps({"name": "mycom-app", "version": __version__()}))
28
+ return 0
29
+ if args.command == "greet":
30
+ print(f"hello, {args.name}")
31
+ return 0
32
+ return 2
33
+
34
+
35
+ def main() -> None:
36
+ sys.exit(run())
37
+
38
+
39
+ if __name__ == "__main__":
40
+ main()
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+
5
+ import pytest
6
+
7
+ from mycom_app import cli
8
+
9
+
10
+ def test_greet_uses_default_name(capsys: pytest.CaptureFixture[str]) -> None:
11
+ assert cli.run(["greet"]) == 0
12
+ assert capsys.readouterr().out.strip() == "hello, world"
13
+
14
+
15
+ def test_greet_uses_given_name(capsys: pytest.CaptureFixture[str]) -> None:
16
+ assert cli.run(["greet", "--name", "lab"]) == 0
17
+ assert capsys.readouterr().out.strip() == "hello, lab"
18
+
19
+
20
+ def test_version_prints_json(capsys: pytest.CaptureFixture[str]) -> None:
21
+ assert cli.run(["version"]) == 0
22
+ payload = json.loads(capsys.readouterr().out)
23
+ assert payload["name"] == "mycom-app"
24
+ assert "version" in payload
25
+
26
+
27
+ def test_missing_command_exits() -> None:
28
+ with pytest.raises(SystemExit) as excinfo:
29
+ cli.run([])
30
+ assert excinfo.value.code != 0