Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
on:
push:
branches:
- main

permissions:
contents: write
issues: write
pull-requests: write

name: release-please

jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.MY_RELEASE_PLEASE_TOKEN }}
release-type: simple
10 changes: 7 additions & 3 deletions diracx-cli/src/diracx/cli/internal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@

def get_repo_path(config_repo_str: str) -> Path:
config_repo = TypeAdapter(ConfigSourceUrl).validate_python(config_repo_str)
if config_repo.scheme != "git+file" or config_repo.path is None:
raise NotImplementedError("Only git+file:// URLs are supported")
if config_repo.scheme not in ("git+file", "file") or config_repo.path is None:
raise NotImplementedError(
"Only git+file:// and file:// URLs are supported for local config repositories"
)

repo_path = Path(config_repo.path)

return repo_path


def get_config_from_repo_path(repo_path: Path) -> Config:
return ConfigSource.create_from_url(backend_url=repo_path).read_config()
return ConfigSource.create_from_url(
backend_url=f"git+file://{repo_path}"
).read_config()


@app.command()
Expand Down
2 changes: 0 additions & 2 deletions diracx-core/src/diracx/core/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from .sources import (
ConfigSource,
ConfigSourceUrl,
LocalGitConfigSource,
RemoteGitConfigSource,
is_running_in_async_context,
)
Expand All @@ -15,7 +14,6 @@
"Config",
"ConfigSource",
"ConfigSourceUrl",
"LocalGitConfigSource",
"RemoteGitConfigSource",
"is_running_in_async_context",
)
62 changes: 19 additions & 43 deletions diracx-core/src/diracx/core/config/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
from datetime import datetime, timezone
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Annotated
from urllib.parse import urlparse, urlunparse

import sh
import yaml
from cachetools import Cache, LRUCache
from pydantic import AnyUrl, BeforeValidator, TypeAdapter, UrlConstraints
from pydantic import AnyUrl, TypeAdapter, UrlConstraints

from ..exceptions import BadConfigurationVersionError
from ..extensions import select_from_extension
Expand All @@ -43,18 +42,11 @@ def is_running_in_async_context():
return False


def _apply_default_scheme(value: str) -> str:
"""Applies the default git+file:// scheme if not present."""
if isinstance(value, str) and "://" not in value:
value = f"git+file://{value}"
return value


class AnyUrlWithoutHost(AnyUrl):
_constraints = UrlConstraints(host_required=False)


ConfigSourceUrl = Annotated[AnyUrlWithoutHost, BeforeValidator(_apply_default_scheme)]
ConfigSourceUrl = AnyUrlWithoutHost


class ConfigSource(metaclass=ABCMeta):
Expand Down Expand Up @@ -233,40 +225,13 @@ def get_git_branch_from_url(self, backend_url: ConfigSourceUrl) -> str:
return dict(backend_url.query_params()).get("branch", DEFAULT_GIT_BRANCH)


class LocalGitConfigSource(BaseGitConfigSource):
"""The configuration is stored on a local git repository
When running on multiple servers, the filesystem must be shared.
"""

scheme = "git+file"

def __init__(self, *, backend_url: ConfigSourceUrl) -> None:
super().__init__(backend_url=backend_url)
if not backend_url.path:
raise ValueError("Empty path for LocalGitConfigSource")

self.repo_location = Path(backend_url.path)
# Check if it's a valid git repository
try:
sh.git(
"rev-parse",
"--git-dir",
_cwd=self.repo_location,
_tty_out=False,
_async=False,
)
except sh.ErrorReturnCode as e:
raise ValueError(
f"{self.repo_location} is not a valid git repository"
) from e
sh.git.checkout(self.git_branch, _cwd=self.repo_location, _async=False)

def __hash__(self):
return hash(self.repo_location)


class RemoteGitConfigSource(BaseGitConfigSource):
"""Use a remote directory as a config source."""
"""Use a remote directory as a config source.

This supports both remote repositories (git+https://) and local repositories
(git+file://). For local repositories, it clones them into a temporary directory
to avoid the file permission issues that LocalGitConfigSource encountered.
"""

scheme = "git+https"

Expand All @@ -292,3 +257,14 @@ def latest_revision(self) -> tuple[str, datetime]:
logger.exception(err)

return super().latest_revision()


class FileGitConfigSource(RemoteGitConfigSource):
"""Alias for RemoteGitConfigSource that handles git+file:// URLs.

This class uses the same implementation as RemoteGitConfigSource,
cloning the local repository into a temporary directory to avoid
file permission issues in containerized environments.
"""

scheme = "git+file"
6 changes: 3 additions & 3 deletions docs/admin/explanations/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ This is in contrast to "Settings" which are only available on the server side.
Confidential information (such as passwords) is only handled in Settings, see the DiracX helm chart for details.

The DiracX configuration is stored as a single YAML file.
We recommend that this is stored within a Git repository, and DiracX provides two git-based backends can be used by servers:
We recommend that this is stored within a Git repository, and DiracX provides git-based backends that can be used by servers:

- `git+file`: Refers to a local git repository. This must be stored on a shared volume which is made available to all DiracX servers.
- `git+https`: Refers to a remote git repository that can be stored on any standard git host.
- `git+https`: Refers to a remote git repository that can be stored on any standard git host. This is the recommended approach for production deployments.
- `git+file`: Refers to a local git repository. This clones the repository into a temporary directory to avoid file permission issues in containerized environments. For production use with local repositories, `git+https` with a local git server is recommended instead.

## Structure of the CS

Expand Down
Loading