Skip to content

Commit 63f1856

Browse files
Switch from dataclass-wizard to mashumaro (#389)
* switch from dataclass-wizard to mashumaro Signed-off-by: Alex Goodman <[email protected]> * split out static analysis from the test matrix Signed-off-by: Alex Goodman <[email protected]> * chore: bump poetry to v1.7.0 Signed-off-by: Weston Steimel <[email protected]> * explicitly pass python version to job matrix Signed-off-by: Alex Goodman <[email protected]> * bust CI cache Signed-off-by: Alex Goodman <[email protected]> * use pip not pipx for poetry install Signed-off-by: Alex Goodman <[email protected]> * remove python 3.12 from the test matrix Signed-off-by: Alex Goodman <[email protected]> * paired matrix vars Signed-off-by: Alex Goodman <[email protected]> * add single test gate Signed-off-by: Alex Goodman <[email protected]> --------- Signed-off-by: Alex Goodman <[email protected]> Signed-off-by: Weston Steimel <[email protected]> Co-authored-by: Weston Steimel <[email protected]>
1 parent 82bea68 commit 63f1856

File tree

13 files changed

+225
-52
lines changed

13 files changed

+225
-52
lines changed

.github/actions/bootstrap/action.yaml

+14-5
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ inputs:
44
go-version:
55
description: "Go version to install"
66
required: true
7-
default: "1.19.x"
7+
default: "1.21.x"
88
python-version:
99
description: "Python version to install"
1010
required: true
11-
default: "3.9"
11+
# note: the caller really drives this in a matrix strategy run for unit tests.
12+
# this default value is used for the rest of the workflow.
13+
default: "3.11"
1214
poetry-version:
1315
description: "Poetry version to install"
1416
required: true
15-
default: "1.3.2"
17+
default: "1.7.0"
1618
use-poetry-cache:
1719
description: "Restore poetry cache"
1820
required: true
@@ -28,7 +30,7 @@ inputs:
2830
cache-key-prefix:
2931
description: "Prefix all cache keys with this value"
3032
required: true
31-
default: "12a830581c"
33+
default: "8381c12a05"
3234
bootstrap-apt-packages:
3335
description: "Space delimited list of tools to install via apt"
3436
default: ""
@@ -49,7 +51,7 @@ runs:
4951
- name: Install poetry
5052
shell: bash
5153
run: |
52-
pipx install poetry==${{ inputs.poetry-version }}
54+
python -m pip install poetry==${{ inputs.poetry-version }}
5355
poetry self add "poetry-dynamic-versioning[plugin]"
5456
5557
- name: Cache Poetry virtualenv
@@ -90,3 +92,10 @@ runs:
9092
- name: Install dependencies and package
9193
shell: bash
9294
run: poetry install
95+
96+
- name: Restore tox cache
97+
id: cache-tox
98+
uses: actions/cache@v3
99+
with:
100+
path: .tox
101+
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('tox.ini') }}

.github/workflows/release.yaml

+15-5
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,22 @@ jobs:
2828
git fetch origin main
2929
git merge-base --is-ancestor ${GITHUB_REF##*/} origin/main && echo "${GITHUB_REF##*/} is a commit on main!"
3030
31-
- name: Check validation results
31+
- name: Check static analysis results
3232
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 #v1.1.1
33-
id: validations
33+
id: static-analysis
3434
with:
3535
token: ${{ secrets.GITHUB_TOKEN }}
3636
# This check name is defined as the github action job name (in .github/workflows/validations.yaml)
37-
checkName: "Validations"
37+
checkName: "Static Analysis"
38+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
39+
40+
- name: Check test results
41+
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 #v1.1.1
42+
id: test
43+
with:
44+
token: ${{ secrets.GITHUB_TOKEN }}
45+
# This check name is defined as the github action job name (in .github/workflows/validations.yaml)
46+
checkName: "Test Gate"
3847
ref: ${{ github.event.pull_request.head.sha || github.sha }}
3948

4049
- name: Check nightly quality gate results
@@ -50,9 +59,10 @@ jobs:
5059
intervalSeconds: 3
5160

5261
- name: Release quality gate
53-
if: steps.validations.conclusion != 'success' || steps.nightly-quality-gate.conclusion != 'success'
62+
if: steps.static-analysis.conclusion != 'success' || steps.test.conclusion != 'success' || steps.nightly-quality-gate.conclusion != 'success'
5463
run: |
55-
echo "Validations Status: ${{ steps.validations.conclusion }}"
64+
echo "Static Analysis Status: ${{ steps.static-analysis.conclusion }}"
65+
echo "Test Status: ${{ steps.test.conclusion }}"
5666
echo "Nightly Quality Gate Status: ${{ steps.nightly-quality-gate.conclusion }}"
5767
false
5868

.github/workflows/validations.yaml

+50-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ on:
1111
jobs:
1212

1313
# note: the name for this check is referenced in release.yaml, do not change here without changing there
14-
Validations:
14+
Static-Analysis:
15+
name: "Static Analysis"
1516
runs-on: ubuntu-22.04
1617
permissions:
1718
contents: read
@@ -27,19 +28,63 @@ jobs:
2728
- name: Run static analysis
2829
run: poetry run make static-analysis
2930

30-
- name: Run unit tests
31-
run: poetry run make unit
32-
3331
- name: Ensure quality gate tools are properly configured
3432
run: |
3533
cd tests/quality && make validate-test-tool-versions
3634
35+
Test:
36+
runs-on: ubuntu-22.04
37+
permissions:
38+
contents: read
39+
strategy:
40+
matrix:
41+
# note: this is not a single source of truth (this is also in the tox.ini)
42+
python:
43+
- version: '3.9'
44+
toxEnv: py39
45+
46+
- version: '3.10'
47+
toxEnv: py310
48+
49+
- version: '3.11'
50+
toxEnv: py311
51+
steps:
52+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
53+
with:
54+
# in order to properly resolve the version from git
55+
fetch-depth: 0
56+
57+
- name: Bootstrap environment
58+
uses: ./.github/actions/bootstrap
59+
with:
60+
python-version: ${{ matrix.python.version }}
61+
62+
- name: Run unit tests
63+
run: poetry run tox -e ${{ matrix.python.toxEnv }}
64+
3765
- name: Build assets
3866
run: poetry run make build
3967

68+
# this is to help facilitate ensuring all checks have run with the checks API for release
69+
# see https://github.com/orgs/community/discussions/26822#discussioncomment-3305794
70+
# as well as the release.yaml workflow
71+
Test-Gate:
72+
if: ${{ always() }}
73+
runs-on: ubuntu-22.04
74+
name: Test Gate
75+
needs: [test]
76+
steps:
77+
- run: |
78+
result="${{ needs.Test.result }}"
79+
if [[ $result == "success" || $result == "skipped" ]]; then
80+
exit 0
81+
else
82+
exit 1
83+
fi
84+
4085
Publish-PreProd:
4186
runs-on: ubuntu-22.04
42-
needs: [Validations]
87+
needs: [Static-Analysis, Test]
4388
if: github.ref == 'refs/heads/main'
4489
permissions:
4590
contents: read

Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ check-types: virtual-env-check ## Run type checks (mypy)
123123
unit: virtual-env-check ## Run unit tests
124124
pytest --cov-report html --cov vunnel -v tests/unit/
125125

126+
.PHONY: unit-matrix
127+
unit-matrix: virtual-env-check ## Run unit tests for all supported python versions
128+
tox
129+
126130

127131
## Build-related targets #################################
128132

poetry.lock

+91-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ xxhash = "^3.1.0"
5151
cvss = "^2.6"
5252
python-dateutil = "^2.8.2"
5353
defusedxml = "^0.7.1"
54-
dataclass-wizard = "^0.22.2"
5554
orjson = "^3.8.6"
5655
SQLAlchemy = ">= 1.4.46, < 2.0" # note: 1.4.x currently required for enterprise
5756
mergedeep = "^1.3.4"
5857
future = "^0.18.3"
5958
importlib-metadata = "^6.1.0"
6059
xsdata = {extras = ["cli", "lxml", "soap"], version = ">=22.12,<24.0"}
6160
pytest-snapshot = "^0.9.0"
61+
mashumaro = "^3.10"
6262

6363
[tool.poetry.group.dev.dependencies]
6464
pytest = "^7.2.2"
@@ -80,6 +80,7 @@ dunamai = "^1.15.0"
8080
ruff = ">=0.0.254,<0.1.5"
8181
yardstick = {git = "https://github.com/anchore/yardstick", rev = "v0.9.1"}
8282
tabulate = "0.9.0"
83+
tox = "^4.11.3"
8384

8485
[build-system]
8586
requires = ["poetry-core>=1.3.0", "poetry-dynamic-versioning"]

pytest.ini

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[pytest]
2+
addopts = -vv --color=yes

src/vunnel/cli/config.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import mergedeep
88
import yaml
9-
from dataclass_wizard import asdict, fromdict
9+
from mashumaro.mixins.dict import DataClassDictMixin
1010

1111
from vunnel import providers
1212

@@ -49,7 +49,7 @@ def __post_init__(self) -> None:
4949

5050

5151
@dataclass
52-
class Application:
52+
class Application(DataClassDictMixin):
5353
root: str = "./data"
5454
log: Log = field(default_factory=Log)
5555
providers: Providers = field(default_factory=Providers)
@@ -60,18 +60,15 @@ def load(path: str = ".vunnel.yaml") -> Application:
6060
with open(path, encoding="utf-8") as f:
6161
app_object = yaml.safe_load(f.read()) or {}
6262
# we need a full default application config first then merge the loaded config on top.
63-
# Why? dataclass_wizard.fromdict() will create instances from the dataclass default
63+
# Why? cls.from_dict() will create instances from the dataclass default
6464
# and NOT the field definition from the container. So it is possible to specify a
6565
# single field in the config and all other fields would be set to the default value
6666
# based on the dataclass definition and not any field(default_factory=...) hints
6767
# from the containing class.
68-
instance = asdict(Application())
68+
instance = Application().to_dict()
6969

7070
mergedeep.merge(instance, app_object)
71-
cfg = fromdict(
72-
Application,
73-
instance,
74-
)
71+
cfg = Application.from_dict(instance)
7572
if cfg is None:
7673
raise FileNotFoundError("parsed empty config")
7774
except FileNotFoundError:

src/vunnel/providers/amazon/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
@dataclass
1616
class Config:
17-
security_advisories: dict[Any, str] = field(default_factory=lambda: amazon_security_advisories)
17+
security_advisories: dict[Any, str] = field(default_factory=lambda: amazon_security_advisories.copy())
1818
runtime: provider.RuntimeConfig = field(
1919
default_factory=lambda: provider.RuntimeConfig(
2020
result_store=result.StoreStrategy.SQLITE,

0 commit comments

Comments
 (0)