dockerfile-analyzer 0.3.23__tar.gz → 0.3.24__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.
- dockerfile_analyzer-0.3.24/.cargo/config.toml +7 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/.github/dependabot.yml +10 -2
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/.github/workflows/CI.yml +65 -47
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/Cargo.lock +3 -45
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/Cargo.toml +1 -2
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/PKG-INFO +1 -2
- dockerfile_analyzer-0.3.24/README.md +226 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/dockerfile_analyzer.pyi +14 -15
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/pyproject.toml +0 -1
- dockerfile_analyzer-0.3.24/src/analyzer.rs +1118 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/src/lib.rs +9 -7
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/src/models.rs +107 -77
- dockerfile_analyzer-0.3.24/src/parse_utils.rs +575 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/tests/test_analyze_dockerfile.py +68 -0
- dockerfile_analyzer-0.3.23/README.md +0 -288
- dockerfile_analyzer-0.3.23/src/analyzer.rs +0 -1513
- dockerfile_analyzer-0.3.23/src/parse_utils.rs +0 -571
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/.gitignore +0 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/LICENSE +0 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/example.py +0 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/py.typed +0 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/requirements-dev.txt +0 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/src/constants.rs +0 -0
- {dockerfile_analyzer-0.3.23 → dockerfile_analyzer-0.3.24}/tests/fixtures/multistage.Dockerfile +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# PyO3 links test and clippy binaries against the interpreter it discovers.
|
|
2
|
+
# `python3` on this machine is 3.12 without libpython3.12.so on the default
|
|
3
|
+
# linker path, so `cargo test` fails with "unable to find library -lpython3.12".
|
|
4
|
+
# Point Cargo at the project virtualenv. CI sets PYO3_PYTHON itself, which
|
|
5
|
+
# overrides this.
|
|
6
|
+
[env]
|
|
7
|
+
PYO3_PYTHON = { value = "env/bin/python", relative = true }
|
|
@@ -5,7 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
version: 2
|
|
7
7
|
updates:
|
|
8
|
-
- package-ecosystem: "cargo"
|
|
9
|
-
directory: "/"
|
|
8
|
+
- package-ecosystem: "cargo"
|
|
9
|
+
directory: "/"
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "weekly"
|
|
12
|
+
- package-ecosystem: "github-actions"
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: "weekly"
|
|
16
|
+
- package-ecosystem: "pip"
|
|
17
|
+
directory: "/"
|
|
10
18
|
schedule:
|
|
11
19
|
interval: "weekly"
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
#
|
|
4
|
-
# maturin generate-ci github
|
|
5
|
-
#
|
|
1
|
+
# Wheel and sdist jobs follow `maturin generate-ci github`.
|
|
2
|
+
# Action refs are pinned to a commit. The comment records the release tag.
|
|
3
|
+
# Lint, cargo test, and python test are project-specific.
|
|
6
4
|
name: CI
|
|
7
5
|
|
|
8
6
|
on:
|
|
9
7
|
push:
|
|
10
8
|
branches:
|
|
11
9
|
- main
|
|
12
|
-
- master
|
|
13
10
|
tags:
|
|
14
11
|
- "*"
|
|
15
12
|
pull_request:
|
|
@@ -18,59 +15,75 @@ on:
|
|
|
18
15
|
permissions:
|
|
19
16
|
contents: read
|
|
20
17
|
|
|
18
|
+
concurrency:
|
|
19
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
20
|
+
cancel-in-progress: true
|
|
21
|
+
|
|
21
22
|
jobs:
|
|
22
23
|
lint:
|
|
23
24
|
name: lint
|
|
24
25
|
runs-on: ubuntu-latest
|
|
25
26
|
steps:
|
|
26
|
-
- uses: actions/checkout@
|
|
27
|
-
- uses: actions/setup-python@
|
|
27
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
28
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
28
29
|
with:
|
|
29
30
|
# Keep in sync with requires-python in pyproject.toml (PyO3 needs a
|
|
30
31
|
# matching libpython for clippy on --all-targets).
|
|
31
32
|
python-version: "3.14"
|
|
32
|
-
-
|
|
33
|
-
uses: dtolnay/rust-toolchain@stable
|
|
33
|
+
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
|
|
34
34
|
with:
|
|
35
|
+
# A commit pin does not get the branch-name default of stable.
|
|
36
|
+
toolchain: stable
|
|
35
37
|
components: rustfmt, clippy
|
|
38
|
+
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
36
39
|
- name: Check formatting
|
|
37
40
|
run: cargo fmt --all -- --check
|
|
38
41
|
- name: Clippy
|
|
39
42
|
run: cargo clippy --all-targets -- -D warnings
|
|
43
|
+
env:
|
|
44
|
+
# setup-python's interpreter is not always `python3` on PATH.
|
|
45
|
+
PYO3_PYTHON: python
|
|
40
46
|
|
|
41
47
|
test:
|
|
42
48
|
name: cargo test
|
|
43
49
|
runs-on: ubuntu-latest
|
|
44
50
|
steps:
|
|
45
|
-
- uses: actions/checkout@
|
|
46
|
-
- uses: actions/setup-python@
|
|
51
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
52
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
47
53
|
with:
|
|
48
54
|
# Keep in sync with requires-python in pyproject.toml (PyO3 needs a
|
|
49
55
|
# matching libpython for linking the test binary).
|
|
50
56
|
python-version: "3.14"
|
|
51
|
-
-
|
|
52
|
-
|
|
57
|
+
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
|
|
58
|
+
with:
|
|
59
|
+
# A commit pin does not get the branch-name default of stable.
|
|
60
|
+
toolchain: stable
|
|
61
|
+
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
53
62
|
- name: Run tests
|
|
54
63
|
run: cargo test
|
|
64
|
+
env:
|
|
65
|
+
# setup-python's interpreter is not always `python3` on PATH.
|
|
66
|
+
PYO3_PYTHON: python
|
|
55
67
|
|
|
56
68
|
python-test:
|
|
57
69
|
name: python test
|
|
58
70
|
runs-on: ubuntu-latest
|
|
59
71
|
steps:
|
|
60
|
-
- uses: actions/checkout@
|
|
61
|
-
- uses: actions/setup-python@
|
|
72
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
73
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
62
74
|
with:
|
|
63
75
|
# Keep in sync with requires-python in pyproject.toml.
|
|
64
76
|
python-version: "3.14"
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
|
|
78
|
+
with:
|
|
79
|
+
# A commit pin does not get the branch-name default of stable.
|
|
80
|
+
toolchain: stable
|
|
81
|
+
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
70
82
|
- name: Install dev dependencies
|
|
71
83
|
run: |
|
|
84
|
+
python -m venv .venv
|
|
72
85
|
source .venv/bin/activate
|
|
73
|
-
pip install -r requirements-dev.txt
|
|
86
|
+
python -m pip install -r requirements-dev.txt
|
|
74
87
|
- name: Build and install extension
|
|
75
88
|
run: |
|
|
76
89
|
source .venv/bin/activate
|
|
@@ -84,6 +97,7 @@ jobs:
|
|
|
84
97
|
needs: [lint, test, python-test]
|
|
85
98
|
runs-on: ${{ matrix.platform.runner }}
|
|
86
99
|
strategy:
|
|
100
|
+
fail-fast: false
|
|
87
101
|
matrix:
|
|
88
102
|
platform:
|
|
89
103
|
- runner: ubuntu-22.04
|
|
@@ -99,8 +113,8 @@ jobs:
|
|
|
99
113
|
- runner: ubuntu-22.04
|
|
100
114
|
target: ppc64le
|
|
101
115
|
steps:
|
|
102
|
-
- uses: actions/checkout@
|
|
103
|
-
- uses: actions/setup-python@
|
|
116
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
117
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
104
118
|
with:
|
|
105
119
|
python-version: 3.x
|
|
106
120
|
- name: Build wheels
|
|
@@ -111,7 +125,7 @@ jobs:
|
|
|
111
125
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
112
126
|
manylinux: auto
|
|
113
127
|
- name: Upload wheels
|
|
114
|
-
uses: actions/upload-artifact@
|
|
128
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
115
129
|
with:
|
|
116
130
|
name: wheels-linux-${{ matrix.platform.target }}
|
|
117
131
|
path: dist
|
|
@@ -120,6 +134,7 @@ jobs:
|
|
|
120
134
|
needs: [lint, test, python-test]
|
|
121
135
|
runs-on: ${{ matrix.platform.runner }}
|
|
122
136
|
strategy:
|
|
137
|
+
fail-fast: false
|
|
123
138
|
matrix:
|
|
124
139
|
platform:
|
|
125
140
|
- runner: ubuntu-22.04
|
|
@@ -131,8 +146,8 @@ jobs:
|
|
|
131
146
|
- runner: ubuntu-22.04
|
|
132
147
|
target: armv7
|
|
133
148
|
steps:
|
|
134
|
-
- uses: actions/checkout@
|
|
135
|
-
- uses: actions/setup-python@
|
|
149
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
150
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
136
151
|
with:
|
|
137
152
|
python-version: 3.x
|
|
138
153
|
- name: Build wheels
|
|
@@ -143,7 +158,7 @@ jobs:
|
|
|
143
158
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
144
159
|
manylinux: musllinux_1_2
|
|
145
160
|
- name: Upload wheels
|
|
146
|
-
uses: actions/upload-artifact@
|
|
161
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
147
162
|
with:
|
|
148
163
|
name: wheels-musllinux-${{ matrix.platform.target }}
|
|
149
164
|
path: dist
|
|
@@ -152,6 +167,7 @@ jobs:
|
|
|
152
167
|
needs: [lint, test, python-test]
|
|
153
168
|
runs-on: ${{ matrix.platform.runner }}
|
|
154
169
|
strategy:
|
|
170
|
+
fail-fast: false
|
|
155
171
|
matrix:
|
|
156
172
|
platform:
|
|
157
173
|
- runner: windows-latest
|
|
@@ -159,8 +175,8 @@ jobs:
|
|
|
159
175
|
- runner: windows-latest
|
|
160
176
|
target: x86
|
|
161
177
|
steps:
|
|
162
|
-
- uses: actions/checkout@
|
|
163
|
-
- uses: actions/setup-python@
|
|
178
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
179
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
164
180
|
with:
|
|
165
181
|
python-version: 3.x
|
|
166
182
|
architecture: ${{ matrix.platform.target }}
|
|
@@ -171,7 +187,7 @@ jobs:
|
|
|
171
187
|
args: --release --out dist --find-interpreter
|
|
172
188
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
173
189
|
- name: Upload wheels
|
|
174
|
-
uses: actions/upload-artifact@
|
|
190
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
175
191
|
with:
|
|
176
192
|
name: wheels-windows-${{ matrix.platform.target }}
|
|
177
193
|
path: dist
|
|
@@ -180,6 +196,7 @@ jobs:
|
|
|
180
196
|
needs: [lint, test, python-test]
|
|
181
197
|
runs-on: ${{ matrix.platform.runner }}
|
|
182
198
|
strategy:
|
|
199
|
+
fail-fast: false
|
|
183
200
|
matrix:
|
|
184
201
|
platform:
|
|
185
202
|
- runner: macos-15-intel
|
|
@@ -187,8 +204,8 @@ jobs:
|
|
|
187
204
|
- runner: macos-14
|
|
188
205
|
target: aarch64
|
|
189
206
|
steps:
|
|
190
|
-
- uses: actions/checkout@
|
|
191
|
-
- uses: actions/setup-python@
|
|
207
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
208
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
192
209
|
with:
|
|
193
210
|
python-version: 3.x
|
|
194
211
|
- name: Build wheels
|
|
@@ -198,7 +215,7 @@ jobs:
|
|
|
198
215
|
args: --release --out dist --find-interpreter
|
|
199
216
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
200
217
|
- name: Upload wheels
|
|
201
|
-
uses: actions/upload-artifact@
|
|
218
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
202
219
|
with:
|
|
203
220
|
name: wheels-macos-${{ matrix.platform.target }}
|
|
204
221
|
path: dist
|
|
@@ -207,14 +224,14 @@ jobs:
|
|
|
207
224
|
needs: [lint, test, python-test]
|
|
208
225
|
runs-on: ubuntu-latest
|
|
209
226
|
steps:
|
|
210
|
-
- uses: actions/checkout@
|
|
227
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
211
228
|
- name: Build sdist
|
|
212
229
|
uses: PyO3/maturin-action@v1
|
|
213
230
|
with:
|
|
214
231
|
command: sdist
|
|
215
232
|
args: --out dist
|
|
216
233
|
- name: Upload sdist
|
|
217
|
-
uses: actions/upload-artifact@
|
|
234
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
218
235
|
with:
|
|
219
236
|
name: wheels-sdist
|
|
220
237
|
path: dist
|
|
@@ -224,24 +241,25 @@ jobs:
|
|
|
224
241
|
runs-on: ubuntu-latest
|
|
225
242
|
if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
|
|
226
243
|
needs: [lint, test, python-test, linux, musllinux, windows, macos, sdist]
|
|
244
|
+
environment:
|
|
245
|
+
name: pypi
|
|
246
|
+
url: https://pypi.org/p/dockerfile-analyzer
|
|
227
247
|
permissions:
|
|
228
|
-
#
|
|
248
|
+
# Sign the release artifacts and mint the PyPI trusted-publishing token.
|
|
229
249
|
id-token: write
|
|
230
|
-
#
|
|
250
|
+
# Upload release artifacts.
|
|
231
251
|
contents: write
|
|
232
|
-
#
|
|
252
|
+
# Generate artifact attestation.
|
|
233
253
|
attestations: write
|
|
234
254
|
steps:
|
|
235
|
-
- uses: actions/download-artifact@
|
|
255
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
236
256
|
- name: Generate artifact attestation
|
|
237
|
-
uses: actions/attest
|
|
257
|
+
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
|
|
238
258
|
with:
|
|
239
259
|
subject-path: "wheels-*/*"
|
|
260
|
+
- name: Install uv
|
|
261
|
+
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
262
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
240
263
|
- name: Publish to PyPI
|
|
241
264
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
242
|
-
|
|
243
|
-
env:
|
|
244
|
-
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
245
|
-
with:
|
|
246
|
-
command: upload
|
|
247
|
-
args: --non-interactive --skip-existing wheels-*/*
|
|
265
|
+
run: uv publish --trusted-publishing always 'wheels-*/*'
|
|
@@ -14,12 +14,11 @@ dependencies = [
|
|
|
14
14
|
|
|
15
15
|
[[package]]
|
|
16
16
|
name = "dockerfile-analyzer"
|
|
17
|
-
version = "0.3.
|
|
17
|
+
version = "0.3.24"
|
|
18
18
|
dependencies = [
|
|
19
19
|
"docker-image",
|
|
20
20
|
"parse-dockerfile",
|
|
21
21
|
"pyo3",
|
|
22
|
-
"serde",
|
|
23
22
|
"shlex",
|
|
24
23
|
]
|
|
25
24
|
|
|
@@ -113,7 +112,7 @@ dependencies = [
|
|
|
113
112
|
"proc-macro2",
|
|
114
113
|
"pyo3-macros-backend",
|
|
115
114
|
"quote",
|
|
116
|
-
"syn
|
|
115
|
+
"syn",
|
|
117
116
|
]
|
|
118
117
|
|
|
119
118
|
[[package]]
|
|
@@ -125,7 +124,7 @@ dependencies = [
|
|
|
125
124
|
"heck",
|
|
126
125
|
"proc-macro2",
|
|
127
126
|
"quote",
|
|
128
|
-
"syn
|
|
127
|
+
"syn",
|
|
129
128
|
]
|
|
130
129
|
|
|
131
130
|
[[package]]
|
|
@@ -162,36 +161,6 @@ version = "0.8.5"
|
|
|
162
161
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
163
162
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
|
164
163
|
|
|
165
|
-
[[package]]
|
|
166
|
-
name = "serde"
|
|
167
|
-
version = "1.0.229"
|
|
168
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
169
|
-
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
|
170
|
-
dependencies = [
|
|
171
|
-
"serde_core",
|
|
172
|
-
"serde_derive",
|
|
173
|
-
]
|
|
174
|
-
|
|
175
|
-
[[package]]
|
|
176
|
-
name = "serde_core"
|
|
177
|
-
version = "1.0.229"
|
|
178
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
179
|
-
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
|
180
|
-
dependencies = [
|
|
181
|
-
"serde_derive",
|
|
182
|
-
]
|
|
183
|
-
|
|
184
|
-
[[package]]
|
|
185
|
-
name = "serde_derive"
|
|
186
|
-
version = "1.0.229"
|
|
187
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
188
|
-
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
|
189
|
-
dependencies = [
|
|
190
|
-
"proc-macro2",
|
|
191
|
-
"quote",
|
|
192
|
-
"syn 3.0.1",
|
|
193
|
-
]
|
|
194
|
-
|
|
195
164
|
[[package]]
|
|
196
165
|
name = "shlex"
|
|
197
166
|
version = "2.0.1"
|
|
@@ -215,17 +184,6 @@ dependencies = [
|
|
|
215
184
|
"unicode-ident",
|
|
216
185
|
]
|
|
217
186
|
|
|
218
|
-
[[package]]
|
|
219
|
-
name = "syn"
|
|
220
|
-
version = "3.0.1"
|
|
221
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
222
|
-
checksum = "5edbec4ed188954a10c12c038215f8ce7606b2d5c973cd8dc43e8795065c5f2f"
|
|
223
|
-
dependencies = [
|
|
224
|
-
"proc-macro2",
|
|
225
|
-
"quote",
|
|
226
|
-
"unicode-ident",
|
|
227
|
-
]
|
|
228
|
-
|
|
229
187
|
[[package]]
|
|
230
188
|
name = "target-lexicon"
|
|
231
189
|
version = "0.13.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "dockerfile-analyzer"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.24"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
|
|
@@ -14,4 +14,3 @@ pyo3 = "0.29.0"
|
|
|
14
14
|
docker-image = {version = "0.2.1"}
|
|
15
15
|
parse-dockerfile = { version = "0.1.7", default-features = false }
|
|
16
16
|
shlex = "2.0.1"
|
|
17
|
-
serde = { version = "1.0.228", features = ["derive"] }
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dockerfile-analyzer
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.24
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
|
-
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
6
|
License-File: LICENSE
|
|
8
7
|
Summary: Analyzes Dockerfiles and provides comprehensive insights including stage information, base images, multistage build analysis, instruction statistics, environment variables, labels, arguments, and exposed ports.
|
|
9
8
|
License-Expression: MIT
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Dockerfile Analyzer
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
This Python package analyzes a Dockerfile and returns detailed analysis information. Some of the metadata returned include:
|
|
6
|
+
|
|
7
|
+
- Number of stages, named stages, and the final stage name
|
|
8
|
+
- Base images, including images pulled by `COPY --from` and `ADD --from`
|
|
9
|
+
- Multistage analysis, with numeric `--from` indexes resolved to stages
|
|
10
|
+
- Instructions statistics
|
|
11
|
+
- Environment variables, labels, and arguments
|
|
12
|
+
- Exposed ports
|
|
13
|
+
|
|
14
|
+
Image references that contain `$` are not expanded. Other image references are lowercased. `EXPOSE` values are returned as written, including protocol suffixes and ranges. A later `ARG NAME` without a default keeps an earlier default.
|
|
15
|
+
|
|
16
|
+
The code leverages the highly useful Rust crates `parse-dockerfile` and `docker-image`.
|
|
17
|
+
|
|
18
|
+
## Example
|
|
19
|
+
|
|
20
|
+
This Dockerfile is short, but it uses the distinctions the analyzer is built to recover: a stage referenced by index, a stage used as a base image, an unused stage, an external `COPY --from` image, a digest-pinned image, an unexpanded variable, and an `ARG` redeclared without a default.
|
|
21
|
+
|
|
22
|
+
### Sample Input Dockerfile
|
|
23
|
+
|
|
24
|
+
```Dockerfile
|
|
25
|
+
# syntax=docker/dockerfile:1.7
|
|
26
|
+
ARG GO_VERSION=1.22
|
|
27
|
+
ARG ALPINE_VERSION=3.20
|
|
28
|
+
ARG VERSION=1.0.0
|
|
29
|
+
|
|
30
|
+
# Stage 0. A later COPY refers to this stage by index.
|
|
31
|
+
FROM alpine:${ALPINE_VERSION} AS tools
|
|
32
|
+
RUN apk add --no-cache ca-certificates
|
|
33
|
+
|
|
34
|
+
FROM golang:${GO_VERSION}-alpine AS build
|
|
35
|
+
WORKDIR /src
|
|
36
|
+
COPY go.mod go.sum ./
|
|
37
|
+
RUN go mod download
|
|
38
|
+
COPY . .
|
|
39
|
+
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app
|
|
40
|
+
|
|
41
|
+
# Uses the build stage as its base image, and is itself an ADD --from source.
|
|
42
|
+
FROM build AS assets
|
|
43
|
+
ADD README.md /docs/README.md
|
|
44
|
+
|
|
45
|
+
# Named, but no later instruction references it.
|
|
46
|
+
FROM alpine:${ALPINE_VERSION} AS debug
|
|
47
|
+
RUN apk add --no-cache busybox
|
|
48
|
+
|
|
49
|
+
# Unnamed, so final_stage is None. Digest is split into components.
|
|
50
|
+
FROM gcr.io/distroless/static-debian12:nonroot@sha256:2c8e1f5d9a3b7e6c4d1f0a8b5e2c9d7f3a6b1c4e8d2f5a9b3c7e1d4f6a8b0c2e
|
|
51
|
+
COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
|
52
|
+
COPY --from=build /out/app /app
|
|
53
|
+
ADD --from=assets /docs/README.md /docs/README.md
|
|
54
|
+
COPY --from=ghcr.io/acme/assets:1.4 /share /share
|
|
55
|
+
# Redeclared with no default, so the global default is kept.
|
|
56
|
+
ARG VERSION
|
|
57
|
+
ENV APP_VERSION=$VERSION
|
|
58
|
+
LABEL org.opencontainers.image.title="app" \
|
|
59
|
+
org.opencontainers.image.version="${VERSION}"
|
|
60
|
+
EXPOSE 8080/tcp 9090/udp
|
|
61
|
+
USER nonroot
|
|
62
|
+
ENTRYPOINT ["/app"]
|
|
63
|
+
CMD ["serve"]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Sample Python Code
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
pip install dockerfile-analyzer
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import json
|
|
74
|
+
|
|
75
|
+
import dockerfile_analyzer as da
|
|
76
|
+
|
|
77
|
+
dockerfile = open("Dockerfile").read()
|
|
78
|
+
analysis = da.analyze_dockerfile(dockerfile)
|
|
79
|
+
|
|
80
|
+
# --from=0 resolved to the tools stage. ghcr.io is an image, not a stage.
|
|
81
|
+
print(analysis.copy_from_stages) # ['build', 'tools']
|
|
82
|
+
print(analysis.copy_from_images[0].components.registry) # ghcr.io
|
|
83
|
+
|
|
84
|
+
# debug is named and never referenced. The final stage is unnamed.
|
|
85
|
+
print(analysis.multistage_analysis.unused_stages) # ['debug']
|
|
86
|
+
print(analysis.final_stage) # None
|
|
87
|
+
|
|
88
|
+
# The second ARG VERSION has no default, so 1.0.0 is kept.
|
|
89
|
+
print(analysis.args["VERSION"]) # 1.0.0
|
|
90
|
+
|
|
91
|
+
print(json.dumps(analysis.to_dict(), indent=2))
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Output
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
['build', 'tools']
|
|
98
|
+
ghcr.io
|
|
99
|
+
['debug']
|
|
100
|
+
None
|
|
101
|
+
1.0.0
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"num_stages": 5,
|
|
106
|
+
"images": [
|
|
107
|
+
{
|
|
108
|
+
"full": "alpine:${ALPINE_VERSION}",
|
|
109
|
+
"components": null
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"full": "build",
|
|
113
|
+
"components": {
|
|
114
|
+
"registry": null,
|
|
115
|
+
"name": "build",
|
|
116
|
+
"tag": null,
|
|
117
|
+
"digest": null
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"full": "gcr.io/distroless/static-debian12:nonroot@sha256:2c8e1f5d9a3b7e6c4d1f0a8b5e2c9d7f3a6b1c4e8d2f5a9b3c7e1d4f6a8b0c2e",
|
|
122
|
+
"components": {
|
|
123
|
+
"registry": "gcr.io",
|
|
124
|
+
"name": "distroless/static-debian12",
|
|
125
|
+
"tag": "nonroot",
|
|
126
|
+
"digest": "sha256:2c8e1f5d9a3b7e6c4d1f0a8b5e2c9d7f3a6b1c4e8d2f5a9b3c7e1d4f6a8b0c2e"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"full": "golang:${GO_VERSION}-alpine",
|
|
131
|
+
"components": null
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"stage_names": [
|
|
135
|
+
"assets",
|
|
136
|
+
"build",
|
|
137
|
+
"debug",
|
|
138
|
+
"tools"
|
|
139
|
+
],
|
|
140
|
+
"final_stage": null,
|
|
141
|
+
"copy_from_stages": [
|
|
142
|
+
"build",
|
|
143
|
+
"tools"
|
|
144
|
+
],
|
|
145
|
+
"add_from_stages": [
|
|
146
|
+
"assets"
|
|
147
|
+
],
|
|
148
|
+
"copy_from_images": [
|
|
149
|
+
{
|
|
150
|
+
"full": "ghcr.io/acme/assets:1.4",
|
|
151
|
+
"components": {
|
|
152
|
+
"registry": "ghcr.io",
|
|
153
|
+
"name": "acme/assets",
|
|
154
|
+
"tag": "1.4",
|
|
155
|
+
"digest": null
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"add_from_images": [],
|
|
160
|
+
"multistage_analysis": {
|
|
161
|
+
"is_multistage": true,
|
|
162
|
+
"stages_used_as_base_images": [
|
|
163
|
+
"build"
|
|
164
|
+
],
|
|
165
|
+
"stages_copied_from": [
|
|
166
|
+
"build",
|
|
167
|
+
"tools"
|
|
168
|
+
],
|
|
169
|
+
"stages_added_from": [
|
|
170
|
+
"assets"
|
|
171
|
+
],
|
|
172
|
+
"unused_stages": [
|
|
173
|
+
"debug"
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
"exposed_ports": [
|
|
177
|
+
"8080/tcp",
|
|
178
|
+
"9090/udp"
|
|
179
|
+
],
|
|
180
|
+
"instructions": {
|
|
181
|
+
"total_count": 27,
|
|
182
|
+
"by_type": {
|
|
183
|
+
"ADD": 2,
|
|
184
|
+
"ARG": 4,
|
|
185
|
+
"CMD": 1,
|
|
186
|
+
"COPY": 5,
|
|
187
|
+
"ENTRYPOINT": 1,
|
|
188
|
+
"ENV": 1,
|
|
189
|
+
"EXPOSE": 1,
|
|
190
|
+
"FROM": 5,
|
|
191
|
+
"LABEL": 1,
|
|
192
|
+
"RUN": 4,
|
|
193
|
+
"USER": 1,
|
|
194
|
+
"WORKDIR": 1
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
"args": {
|
|
198
|
+
"ALPINE_VERSION": "3.20",
|
|
199
|
+
"GO_VERSION": "1.22",
|
|
200
|
+
"VERSION": "1.0.0"
|
|
201
|
+
},
|
|
202
|
+
"labels": {
|
|
203
|
+
"org.opencontainers.image.title": "app",
|
|
204
|
+
"org.opencontainers.image.version": "${VERSION}"
|
|
205
|
+
},
|
|
206
|
+
"env_vars": {
|
|
207
|
+
"APP_VERSION": "$VERSION"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Developing
|
|
213
|
+
|
|
214
|
+
```sh
|
|
215
|
+
python3 -m venv env
|
|
216
|
+
source env/bin/activate
|
|
217
|
+
pip install -r requirements-dev.txt
|
|
218
|
+
cargo fmt --all -- --check
|
|
219
|
+
cargo clippy --all-targets -- -D warnings
|
|
220
|
+
cargo test
|
|
221
|
+
maturin develop
|
|
222
|
+
pytest
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`cargo test` and `cargo clippy --all-targets` link against libpython. `.cargo/config.toml` points PyO3 at `env/bin/python`, which must be a shared Python build (`libpython3.x.so` present). `PYO3_PYTHON` overrides that path when set.
|
|
226
|
+
|
|
@@ -7,13 +7,17 @@ def analyze_dockerfile(body: str) -> Analysis:
|
|
|
7
7
|
dockerfile_content (str): The content of the Dockerfile to analyze
|
|
8
8
|
|
|
9
9
|
Returns:
|
|
10
|
-
Analysis:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
Analysis: Stages, images, instruction counts, ARG/ENV/LABEL values,
|
|
11
|
+
and exposed ports. ``COPY --from`` and ``ADD --from`` indexes are
|
|
12
|
+
resolved to stages. External ``--from`` images are returned separately
|
|
13
|
+
from stage names.
|
|
14
|
+
|
|
15
|
+
Image references that do not contain a variable are lowercased.
|
|
16
|
+
``${VAR}`` and ``$VAR`` are not expanded. ``EXPOSE`` values are raw
|
|
17
|
+
tokens, including protocol suffixes and ranges. ``stage_names`` lists
|
|
18
|
+
named stages only; ``final_stage`` is the last stage name, or None
|
|
19
|
+
when it is unnamed. A later ``ARG NAME`` without a value keeps an
|
|
20
|
+
earlier default.
|
|
17
21
|
|
|
18
22
|
Raises:
|
|
19
23
|
ValueError: If the dockerfile content is empty or invalid
|
|
@@ -31,8 +35,11 @@ class Analysis:
|
|
|
31
35
|
num_stages: int
|
|
32
36
|
images: List[Image]
|
|
33
37
|
stage_names: List[str]
|
|
38
|
+
final_stage: Optional[str]
|
|
34
39
|
copy_from_stages: List[str]
|
|
35
40
|
add_from_stages: List[str]
|
|
41
|
+
copy_from_images: List[Image]
|
|
42
|
+
add_from_images: List[Image]
|
|
36
43
|
multistage_analysis: MultistageAnalysis
|
|
37
44
|
exposed_ports: List[str]
|
|
38
45
|
instructions: InstructionStats
|
|
@@ -75,11 +82,3 @@ class MultistageAnalysis:
|
|
|
75
82
|
|
|
76
83
|
def to_dict(self) -> Dict[str, Any]: ...
|
|
77
84
|
def __repr__(self) -> str: ...
|
|
78
|
-
|
|
79
|
-
class KeyValueInstr:
|
|
80
|
-
args: Dict[str, Optional[str]]
|
|
81
|
-
labels: Dict[str, str]
|
|
82
|
-
env_vars: Dict[str, str]
|
|
83
|
-
|
|
84
|
-
def to_dict(self) -> Dict[str, Any]: ...
|
|
85
|
-
def __repr__(self) -> str: ...
|