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.
- mycom_app-0.1.0/.github/CODEOWNERS +4 -0
- mycom_app-0.1.0/.github/workflows/ci.yml +50 -0
- mycom_app-0.1.0/.gitignore +7 -0
- mycom_app-0.1.0/Dockerfile +19 -0
- mycom_app-0.1.0/PKG-INFO +48 -0
- mycom_app-0.1.0/README.md +34 -0
- mycom_app-0.1.0/pyproject.toml +33 -0
- mycom_app-0.1.0/src/mycom_app/__init__.py +21 -0
- mycom_app-0.1.0/src/mycom_app/cli.py +40 -0
- mycom_app-0.1.0/tests/test_cli.py +30 -0
|
@@ -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,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"]
|
mycom_app-0.1.0/PKG-INFO
ADDED
|
@@ -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
|