Skip to content

Commit

Permalink
Merge branch 'main' into rtd-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
medubelko committed Jan 14, 2025
2 parents f6b2fd1 + f65ecc0 commit feb170e
Show file tree
Hide file tree
Showing 55 changed files with 1,368 additions and 496 deletions.
186 changes: 1 addition & 185 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
@@ -1,187 +1,3 @@
{
// Configuration file for RenovateBot: https://docs.renovatebot.com/configuration-options
extends: ["config:recommended", ":semanticCommitTypeAll(build)"],
ignoreDeps: [
// Each ignore is probably connected with an ignore in pyproject.toml.
// Ensure you change this and those simultaneously.
"urllib3",
// Temporary until we remove Windows. https://github.com/canonical/charmcraft/issues/1810
"windows", // We'll update Windows versions manually.
"tox-gh", // As of 1.3.2 tox-gh doesn't support Windows 2019's python 3.7.
],
labels: ["dependencies"], // For convenient searching in GitHub
baseBranches: ["$default", "/^hotfix\\/.*/"],
pip_requirements: {
fileMatch: ["^tox.ini$", "(^|/)requirements([\\w-]*)\\.txt$", "^.pre-commit-config.yaml$"]
},
packageRules: [
{
// Internal package minor patch updates get top priority, with auto-merging
groupName: "internal package minor releases",
matchPackagePatterns: ["^craft-.*"],
matchUpdateTypes: ["minor", "patch", "pin", "digest"],
prPriority: 10,
automerge: true,
minimumReleaseAge: "0 seconds",
schedule: ["at any time"],
matchBaseBranches: ["$default"], // Only do minor releases on main
},
{
// Same as above, but for hotfix branches, only for patch, and without auto-merging.
groupName: "internal package patch releases (hotfix)",
matchPackagePatterns: ["^craft-.*"],
matchUpdateTypes: ["patch", "pin", "digest"],
prPriority: 10,
minimumReleaseAge: "0 seconds",
schedule: ["at any time"],
matchBaseBranches: ["/^hotfix\\/.*/"], // All hotfix branches
},
{
// Automerge patches, pin changes and digest changes.
// Also groups these changes together.
groupName: "bugfixes",
excludeDepPatterns: [
"lint/.*",
"types/.*",
"pyright", // Pyright needs to be done separately.
],
matchUpdateTypes: ["patch", "pin", "digest"],
prPriority: 3, // Patches should go first!
automerge: true
},
{
// Update all internal packages in one higher-priority PR
groupName: "internal packages",
matchDepPatterns: ["craft-.*", "snap-.*"],
matchCategories: ["python"],
prPriority: 2,
matchBaseBranches: ["$default"], // Not for hotfix branches
},
{
// GitHub Actions are higher priority to update than most dependencies since they don't tend to break things.
groupName: "GitHub Actions",
matchManagers: ["github-actions"],
prPriority: 1,
automerge: true,
},
// Everything not in one of these rules gets priority 0 and falls here.
{
//Do all pydantic-related updates together
groupName: "pydantic etc.",
matchPackagePatterns: ["^pydantic"],
},
{
// Minor changes can be grouped and automerged for dev dependencies, but are also deprioritised.
groupName: "development dependencies (non-major)",
groupSlug: "dev-dependencies",
matchDepPatterns: [
"dev/.*",
"lint/.*",
"types/.*"
],
matchPackagePatterns: [
// Brought from charmcraft. May not be complete.
// This helps group dependencies in requirements-dev.txt files.
"^(.*/)?autoflake$",
"^(.*/)?black$",
"^(.*/)?codespell$",
"^(.*/)?coverage$",
"^(.*/)?flake8$",
"^(.*/)?hypothesis$",
"^(.*/)?mypy$",
"^(.*/)?pycodestyle$",
"^(.*/)?docstyle$",
"^(.*/)?pyfakefs$",
"^(.*/)?pyflakes$",
"^(.*/)?pylint$",
"^(.*/)?pytest",
"^(.*/)?responses$",
"^(.*/)?ruff$",
"^(.*/)?twine$",
"^(.*/)?tox$",
"^(.*/)?types-",
],
matchUpdateTypes: ["minor", "patch", "pin", "digest"],
prPriority: -1,
automerge: true
},
{
// Documentation related updates
groupName: "documentation dependencies",
groupSlug: "doc-dependencies",
matchPackageNames: ["Sphinx", "furo"],
matchPackagePatterns: ["[Ss]phinx.*$"],
matchDepPatterns: ["docs/.*"],
matchBaseBranches: ["$default"], // Not for hotfix branches
},
{
// Other major dependencies get deprioritised below minor dev dependencies.
matchUpdateTypes: ["major"],
prPriority: -2,
matchBaseBranches: ["$default"], // Not for hotfix branches
},
{
// Major dev dependencies are stone last, but grouped.
groupName: "development dependencies (major versions)",
groupSlug: "dev-dependencies",
matchDepTypes: ["devDependencies"],
matchUpdateTypes: ["major"],
prPriority: -3,
matchBaseBranches: ["$default"], // Not for hotfix branches
matchPackagePatterns: [
// Generated from the dependency dashboard, may not be complete.
"^(.*/)?autoflake$",
"^(.*/)?black$",
"^(.*/)?flake8$",
"^(.*/)?hypothesis$",
"^(.*/)?pycodestyle$",
"^(.*/)?pyfakefs$",
"^(.*/)?pyflakes$",
"^(.*/)?pylint$",
"^(.*/)?pytest",
"^(.*/)?responses$",
"^(.*/)?ruff$",
"^(.*/)?twine$",
"^(.*/)?types-"
],
},
{
// Pyright makes regular breaking changes in patch releases, so we separate these
// and do them independently.
matchPackageNames: ["pyright", "types/pyright"],
prPriority: -4,
matchBaseBranches: ["$default"], // Not for hotfix branches
}
],
customManagers: [
{
// tox.ini can get updates too if we specify for each package.
fileMatch: ["tox.ini"],
customType: "regex",
depTypeTemplate: "devDependencies",
matchStrings: [
"# renovate: datasource=(?<datasource>\\S+)\n\\s+(?<depName>.*?)(\\[[\\w]*\\])*[=><]=?(?<currentValue>.*?)\n"
]
},
{
// .pre-commit-config.yaml version updates
fileMatch: [".pre-commit-config.yaml"],
customType: "regex",
datasourceTemplate: "pypi",
depTypeTemplate: "lint",
matchStrings: [
"- repo: .*/<(?<depName>\\S+)\\s*\\n\\s*rev:\s+\"?v?(?<currentValue>\\S*)\"?",
]
}
],
timezone: "Etc/UTC",
schedule: ["every weekend"],
prConcurrentLimit: 2, // No more than 2 open PRs at a time.
branchConcurrentLimit: 20, // No more than 20 open branches at a time.
prCreation: "not-pending", // Wait until status checks have completed before raising the PR
prNotPendingHours: 4, // ...unless the status checks have been running for 4+ hours.
prHourlyLimit: 1, // No more than 1 PR per hour.
minimumReleaseAge: "2 days",
automergeStrategy: "squash", // Squash & rebase when auto-merging.
semanticCommitType: "build" // use `build` as commit header type (i.e. `build(deps): <description>`)
extends: ["github>canonical/starflow:renovate.json5"],
}
3 changes: 3 additions & 0 deletions .github/workflows/spread-large.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ on:
pull_request:
paths:
- .github/workflows/spread-large.yaml
- tests/spread/charms/**
- tests/spread/smoketests/parallel-build/*
- tests/spread/smoketests/remote-build/*

# Only ever run one of this test at a time.
concurrency:
Expand Down
8 changes: 2 additions & 6 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,7 @@ jobs:
fetch-depth: 0
- name: Set up uv with caching
id: setup-uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
uses: astral-sh/setup-uv@v5
- name: Install dependencies
run: |
uv sync --no-dev
Expand Down Expand Up @@ -191,9 +189,7 @@ jobs:
uses: actions/checkout@v4
- name: Set up uv with caching
id: setup-uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
uses: astral-sh/setup-uv@v5
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ ipython_config.py
# Pycharm
.idea

# VS Code
.vscode

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repos:
- id: fix-byte-order-marker
- id: mixed-line-ending
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.8.1"
rev: "v0.9.0"
hooks:
# Run the linter
- id: ruff
Expand Down
4 changes: 4 additions & 0 deletions charmcraft/extensions/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ def get_image_name(self) -> str:
"type": "int",
"description": "The number of webserver worker processes for handling requests.",
},
"webserver-worker-class": {
"type": "string",
"description": "The webserver worker process class for handling requests. Can be either 'gevent' or 'sync'.",
},
}


Expand Down
32 changes: 24 additions & 8 deletions charmcraft/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from craft_platforms import charm
from craft_providers import bases
from pydantic import dataclasses
from typing_extensions import Self
from typing_extensions import Self, override

from charmcraft import const, preprocess, utils
from charmcraft.const import (
Expand Down Expand Up @@ -323,6 +323,15 @@ class CharmcraftBuildPlanner(models.BuildPlanner):
build_base: str | None = None
platforms: dict[str, models.Platform | None] | None = None # type: ignore[assignment]

@override
@pydantic.field_validator("platforms", mode="before")
@classmethod
def _populate_platforms(cls, platforms: dict[str, Any]) -> dict[str, Any]:
"""Overrides the validator to prevent platforms from being modified.
Modifying the platforms field can break multi-base builds."""
return platforms

def get_build_plan(self) -> list[models.BuildInfo]:
"""Get build bases for this charm.
Expand All @@ -346,13 +355,9 @@ def get_build_plan(self) -> list[models.BuildInfo]:
),
)
]
if not self.base:
if not self.base and not self.platforms:
return list(CharmBuildInfo.gen_from_bases_configurations(*self.bases))

build_base = self.build_base or self.base
base_name, _, base_version = build_base.partition("@")
base = bases.BaseName(name=base_name, version=base_version)

if self.platforms is None:
raise CraftError("Must define at least one platform.")
platforms = cast(
Expand All @@ -373,7 +378,9 @@ def get_build_plan(self) -> list[models.BuildInfo]:
platform=info.platform,
build_on=str(info.build_on),
build_for=str(info.build_for),
base=base,
base=bases.BaseName(
name=info.build_base.distribution, version=info.build_base.series
),
)
for info in build_infos
]
Expand Down Expand Up @@ -1064,7 +1071,7 @@ class PlatformCharm(CharmProject):
"""Model for defining a charm using Platforms."""

# Silencing pyright because it complains about missing default value
base: BaseStr # pyright: ignore[reportGeneralTypeIssues]
base: BaseStr | None = None
build_base: BuildBaseStr | None = None
platforms: dict[str, models.Platform | None] # type: ignore[assignment]

Expand All @@ -1076,6 +1083,15 @@ def _validate_dev_base_needs_build_base(self) -> Self:
)
return self

@override
@pydantic.field_validator("platforms", mode="before")
@classmethod
def _populate_platforms(cls, platforms: dict[str, Any]) -> dict[str, Any]:
"""Overrides the validator to prevent platforms from being modified.
Modifying the platforms field can break multi-base builds."""
return platforms


Charm = BasesCharm | PlatformCharm

Expand Down
1 change: 1 addition & 0 deletions charmcraft/parts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def get_app_plugins() -> dict[str, type[craft_parts.plugins.Plugin]]:
"poetry": plugins.PoetryPlugin,
"python": plugins.PythonPlugin,
"reactive": plugins.ReactivePlugin,
"uv": plugins.UvPlugin,
}


Expand Down
4 changes: 4 additions & 0 deletions charmcraft/parts/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from ._poetry import PoetryPlugin, PoetryPluginProperties
from ._python import PythonPlugin, PythonPluginProperties
from ._reactive import ReactivePlugin, ReactivePluginProperties
from ._uv import UvPlugin
from craft_parts.plugins.uv_plugin import UvPluginProperties

__all__ = [
"BundlePlugin",
Expand All @@ -33,4 +35,6 @@
"PythonPluginProperties",
"ReactivePlugin",
"ReactivePluginProperties",
"UvPlugin",
"UvPluginProperties",
]
Loading

0 comments on commit feb170e

Please sign in to comment.