docker-image-pin 0.4.1__py3-none-any.whl → 0.4.2__py3-none-any.whl

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.
@@ -35,7 +35,95 @@ def parse_args() -> Args:
35
35
  return parser.parse_args(namespace=Args())
36
36
 
37
37
 
38
- def main() -> int: # noqa: C901, PLR0912, PLR0915, FIX002, TD003 # TODO(GideonBear): extract line to function
38
+ def process_line(file: Path, lnr: int, line: str) -> int: # noqa: C901, PLR0911, PLR0912
39
+ def log(msg: str) -> None:
40
+ print(f"({file}:{lnr + 1}) {msg}")
41
+
42
+ def invalid(msg: str) -> int:
43
+ log(f"Invalid: {msg}")
44
+ return 1
45
+
46
+ def warn(msg: str) -> None:
47
+ log(f"Warning: {msg}")
48
+
49
+ line = line.strip()
50
+ if not (line.startswith(("image:", "FROM"))):
51
+ return 0
52
+
53
+ allow = None
54
+ if "#" in line:
55
+ line, comment = line.split("#")
56
+ line = line.strip()
57
+ comment = comment.strip()
58
+ if comment.startswith("allow-"):
59
+ allow = comment.removeprefix("allow-")
60
+
61
+ if allow == "all":
62
+ return 0
63
+
64
+ line = line.removeprefix("image:").strip()
65
+ line = line.removeprefix("FROM").strip()
66
+ try:
67
+ rest, sha = line.split("@")
68
+ except ValueError:
69
+ return invalid("no '@'")
70
+ try:
71
+ image, version = rest.split(":")
72
+ except ValueError:
73
+ return invalid("no ':' in leading part")
74
+
75
+ default_allow = default_allows.get(image)
76
+ if default_allow:
77
+ if allow:
78
+ warn(
79
+ "allow comment specified while "
80
+ "there is a default allow for this image. "
81
+ f"(specified '{allow}', default '{default_allow}')"
82
+ )
83
+ allow = default_allow
84
+
85
+ if version in {"latest", "stable"}:
86
+ if allow != version:
87
+ return invalid(
88
+ f"[{version}] uses dynamic tag '{version}' instead of pinned version"
89
+ )
90
+ else:
91
+ if "-" in version:
92
+ version, _extra = version.split("-")
93
+ version = version.removeprefix("v") # Optional prefix
94
+ parts = version.split(".")
95
+ if len(parts) > 3 and allow != "weird-version": # noqa: PLR2004
96
+ # major.minor.patch.???
97
+ return invalid(
98
+ "[weird-version] version contains more than three parts "
99
+ "(major.minor.patch.???)"
100
+ )
101
+ if len(parts) == 2 and allow != "major-minor": # noqa: PLR2004
102
+ # major.minor
103
+ return invalid(
104
+ "[major-minor] version contains only two parts (major.minor). "
105
+ "Can the version be pinned further?"
106
+ )
107
+ if len(parts) == 1 and allow != "major":
108
+ # major
109
+ return invalid(
110
+ "[major] version contains only one part (major). "
111
+ "Can the version be pinned further?"
112
+ )
113
+ if len(parts) == 0:
114
+ msg = "Unreachable"
115
+ raise AssertionError(msg)
116
+
117
+ if not sha.startswith("sha256:"):
118
+ return invalid("invalid hash (doesn't start with 'sha256:'")
119
+ sha = sha.removeprefix("sha256:")
120
+ if not is_valid_sha256(sha):
121
+ return invalid("invalid sha256 digest")
122
+
123
+ return 0
124
+
125
+
126
+ def main() -> int:
39
127
  args = parse_args()
40
128
 
41
129
  retval = 0
@@ -43,100 +131,9 @@ def main() -> int: # noqa: C901, PLR0912, PLR0915, FIX002, TD003 # TODO(Gideon
43
131
  content = file.read_text()
44
132
 
45
133
  for lnr, line in enumerate(content.splitlines()):
46
-
47
- def log(msg: str) -> None:
48
- print(f"({file}:{lnr + 1}) {msg}") # noqa: B023
49
-
50
- def invalid(msg: str) -> None:
51
- nonlocal retval
134
+ line_retval = process_line(file, lnr, line)
135
+ if line_retval == 1:
52
136
  retval = 1
53
- log(f"Invalid: {msg}")
54
-
55
- def warn(msg: str) -> None:
56
- log(f"Warning: {msg}")
57
-
58
- line = line.strip()
59
- if not (line.startswith(("image:", "FROM"))):
60
- continue
61
-
62
- allow = None
63
- if "#" in line:
64
- line, comment = line.split("#")
65
- line = line.strip()
66
- comment = comment.strip()
67
- if comment.startswith("allow-"):
68
- allow = comment.removeprefix("allow-")
69
-
70
- line = line.removeprefix("image:").strip()
71
- line = line.removeprefix("FROM").strip()
72
- try:
73
- rest, sha = line.split("@")
74
- except ValueError:
75
- invalid("no '@'")
76
- continue
77
- try:
78
- image, version = rest.split(":")
79
- except ValueError:
80
- invalid("no ':' in leading part")
81
- continue
82
-
83
- default_allow = default_allows.get(image)
84
- if default_allow:
85
- if allow:
86
- warn(
87
- "allow comment specified while "
88
- "there is a default allow for this image. "
89
- f"(specified '{allow}', default '{default_allow}')"
90
- )
91
- allow = default_allow
92
-
93
- if version in {"latest", "stable"}:
94
- if allow != version:
95
- invalid(
96
- f"[{version}] uses dynamic tag '{version}' "
97
- f"instead of pinned version"
98
- )
99
- continue
100
- else:
101
- if "-" in version:
102
- version, _extra = version.split("-")
103
- version = version.removeprefix("v") # Optional prefix
104
- parts = version.split(".")
105
- if len(parts) == 3: # noqa: PLR2004
106
- # major.minor.patch
107
- continue
108
- if len(parts) > 3 and allow != "weird-version": # noqa: PLR2004
109
- # major.minor.patch.???0
110
- invalid(
111
- "[weird-version] version contains more than three parts "
112
- "(major.minor.patch.???)"
113
- )
114
- continue
115
- if len(parts) == 2 and allow != "major-minor": # noqa: PLR2004
116
- # major.minor
117
- invalid(
118
- "[major-minor] version contains only two parts (major.minor). "
119
- "Can the version be pinned further?"
120
- )
121
- continue
122
- if len(parts) == 1 and allow != "major":
123
- # major
124
- invalid(
125
- "[major] version contains only one part (major). "
126
- "Can the version be pinned further?"
127
- )
128
- continue
129
- if len(parts) == 0:
130
- msg = "Unreachable"
131
- raise AssertionError(msg)
132
-
133
- if not sha.startswith("sha256:"):
134
- invalid("invalid hash (doesn't start with 'sha256:'")
135
- continue
136
- sha = sha.removeprefix("sha256:")
137
- if not is_valid_sha256(sha):
138
- invalid("invalid sha256 digest")
139
- continue
140
137
 
141
138
  return retval
142
139
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docker-image-pin
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: Checks if Docker images are properly pinned in docker-compose.yml and Dockerfile files
5
5
  Author: GideonBear
6
6
  License-Expression: GPL-3.0-only
@@ -0,0 +1,5 @@
1
+ docker_image_pin/__init__.py,sha256=y0EjMSxXGMmwSzO_ctOiVCHyJOBvwxNDu63gmU_O3E4,3925
2
+ docker_image_pin-0.4.2.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
3
+ docker_image_pin-0.4.2.dist-info/entry_points.txt,sha256=xbY6M80EH8T623wyl6-X7VsLB0iPGx517EGocTvsVco,60
4
+ docker_image_pin-0.4.2.dist-info/METADATA,sha256=-Nw6HCBvEA500-7TWe7GCSJ0N0NvaXYBoGM7TOgi7ow,1454
5
+ docker_image_pin-0.4.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.8.15
2
+ Generator: uv 0.8.24
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,5 +0,0 @@
1
- docker_image_pin/__init__.py,sha256=qk_1IOY27zduyHk6t-1SsTDGodzsLVmcfXbIjir7cxE,4692
2
- docker_image_pin-0.4.1.dist-info/WHEEL,sha256=Jb20R3Ili4n9P1fcwuLup21eQ5r9WXhs4_qy7VTrgPI,79
3
- docker_image_pin-0.4.1.dist-info/entry_points.txt,sha256=xbY6M80EH8T623wyl6-X7VsLB0iPGx517EGocTvsVco,60
4
- docker_image_pin-0.4.1.dist-info/METADATA,sha256=WpXq4F1IYXCiA8VRNDwPAc_r9W3vsF696OZjrSxPVAc,1454
5
- docker_image_pin-0.4.1.dist-info/RECORD,,