{"id":31919985,"url":"https://github.com/pulp/pulp-manager","last_synced_at":"2025-10-13T21:52:12.793Z","repository":{"id":313213331,"uuid":"1031675413","full_name":"pulp/Pulp-manager","owner":"pulp","description":"Coordinate multi-cluster Pulp3 deployments across diverse security zones","archived":false,"fork":false,"pushed_at":"2025-10-02T17:30:22.000Z","size":1071,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-02T19:23:50.533Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pulp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-04T06:58:09.000Z","updated_at":"2025-10-01T15:54:10.000Z","dependencies_parsed_at":"2025-09-04T16:29:47.767Z","dependency_job_id":"3f632051-251a-407b-8f25-81f6804dc84f","html_url":"https://github.com/pulp/Pulp-manager","commit_stats":null,"previous_names":["g-research/pulp-manager","pulp/pulp-manager"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pulp/Pulp-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulp%2FPulp-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulp%2FPulp-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulp%2FPulp-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulp%2FPulp-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pulp","download_url":"https://codeload.github.com/pulp/Pulp-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pulp%2FPulp-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279017030,"owners_count":26085951,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-13T21:52:07.403Z","updated_at":"2025-10-13T21:52:12.784Z","avatar_url":"https://github.com/pulp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pulp Manager\n\n![CI](https://github.com/G-Research/Pulp-manager/workflows/CI/badge.svg)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n\n## Project Description\n\nThe Pulp Manager application is used to coordinate common Pulp\nworkflows and provide additional reporting capabilities about a\ncluster of Pulp servers. It is designed to work with Pulp3 servers in\na primary/secondary setup.\n\n## Why Pulp Manager?\n\nPulp Manager provides centralized orchestration of a cluster of Pulp3\ninstances. It is particularly useful for organizations with\nmulti-tiered or multi-zone deployments who need coordinated syncs\nbetween primary and secondary servers.\n\nPulp3 doesn't provide a method to schedule the synchronisation of\nrepos, and in some repository types (deb) may require multiple steps\nto sync and update a repo's content. Pulp Manager provides the\ncoordination and reporting for this (along with other workflows),\nrather than using a more generic management approach such as Ansible\nor Jenkins.\n\n## Core Team\n\nThis project originated at [G-Research](https://github.com/G-Research)\nbut is now owned by the Pulp project. For details on our team and\nroles, please see the [MAINTAINERS.md](MAINTAINERS.md) file.\n\n## Documentation Index\n\n- [Quick Start](#quick-start) - Get up and running quickly\n- [API Documentation](#api-documentation) - Interactive API docs\n- [Application Configuration](#application-configuration) - Config\n  file reference\n- [Sync Configuration](#sync-configuration) - YAML config reference\n- [Development Info](#development-info) - Development setup and\n  workflow\n- [Architecture](#architecture) - System design overview\n- [Troubleshooting](#troubleshooting) - Common issues and solutions\n\n## Repository Structure\n\nThe main code for the application lives in the app directory and split\ninto the following main folders:\n- **models**: SQLAlchemy models which map back to database tables\n- **repositories**: Classes that interact with the models. Each\n  repository inherits from TableRepository, which contains generic\n  operations for CRUD actions. On the filter method relationships\n  directly attached to the entity can be eagerly loaded by specifying\n  their name in the eager option. 1 model has 1 repository\n- **services**: This contains the main business logic of the app,\n  services will make use of multiple table repositories for\n  interacting with the DB and also carry out the commits and rollbacks\n- **utils**: Utilities common across the app, e.g. logging\n\n## Development and Software Delivery Lifecycle\n\nThis project uses GitHub Actions for CI/CD with DevContainer\nintegration:\n\n- **Automated Testing**: All tests run in the same DevContainer\n  environment used for development\n- **Linting**: Code quality checks with pylint\n- **Coverage Reporting**: Test coverage analysis with pytest-cov (90%\n  threshold required)\n- **Multiple Test Strategies**: Both direct pytest and `make t`\n  execution\n\nThe CI workflows are defined in `.github/workflows/`:\n- `test.yml`: Quick test execution on pushes and PRs\n- `ci.yml`: Comprehensive CI with linting, testing, and coverage\n  reporting\n\n## Why Synchronous APIs?\n\nThis application uses synchronous APIs rather than async for practical\nreasons:\n- Background jobs are handled by RQ workers (Redis Queue)\n- RQ workers process one job at a time in a single process\n- Database operations and external libraries (e.g., HashiCorp Vault)\n  are synchronous\n- The API doesn't experience high traffic volumes that would benefit\n  from async handling\n\n## Architecture\n\nThe application follows a layered architecture with five main\ncomponents:\n\n1. **REST API** (port 8080 local, 443 production) - FastAPI\n   application serving `/v1` endpoints\n2. **Worker** - RQ-based background task processor for long-running\n   operations\n3. **Scheduler** - RQ scheduler for recurring tasks based on\n   `pulp_config.yml`\n4. **Exporter** (port 9300) - Prometheus metrics exporter for\n   monitoring\n5. **RQ Dashboard** - Web UI for monitoring background jobs\n\n### Code Organization\n\n- **`pulp_manager/app/`** - Main application code\n  - **`models/`** - SQLAlchemy ORM models mapping to database tables\n  - **`repositories/`** - Data access layer, each inheriting from\n    `TableRepository` for CRUD operations\n  - **`services/`** - Business logic layer coordinating repositories\n    and external services\n  - **`routers/v1/`** - FastAPI route definitions and request handlers\n  - **`schemas/`** - Pydantic models for API request/response\n    validation\n  - **`tasks/`** - Background task definitions for RQ workers\n  - **`auth/`** - LDAP authentication and JWT token handling\n\n- **`pulp3_bindings/`** - Custom Pulp 3 API client library\n- **`hashi_vault_client/`** - HashiCorp Vault integration for secrets\n  management\n\n### Key Services\n\n- **PulpManager** - Core service orchestrating Pulp operations\n- **Reconciler** - Ensures Pulp state matches configuration\n- **RepoSyncher** - Manages repository synchronization\n- **Snapshotter** - Creates repository snapshots\n- **PulpConfigParser** - Processes `pulp_config.yml` configuration\n\n## Quick Start\n\n1. **For Development (running tests, exploring APIs, etc) **\n   ```bash\n   # Open in VS Code and select action \"Dev Containers: Reopen in Container\"\n   # Or use the Dev Container CLI:\n   devcontainer up --workspace-folder .\n   ```\n   \n   From a terminal in the devcontainer, 'make t' will run the tests.\n \n\n2. **For Demo cluster, use the make target to setup a complete Docker Compose environment**\n   ```bash\n   make demo\n   ```\n   \n   When startup is finished, `docker ps` will show you the components, and all APIs will be listening.\n\nFor detailed development setup, see the [Development\nInfo](#development-info) section.\n\n## API Documentation\n\nOnce the application is running, API documentation is available at:\n- Swagger UI: http://localhost:8080/docs\n- ReDoc: http://localhost:8080/redoc\n\n## Application configuration\n\nAn ini file is used to define application settings. A sample ini along\nwith explanation of sections is given below. File needs to be deployed\nto /etc/pulp_manager/config.ini\n\n```\n[ca]\nroot_ca_file_path=/etc/pulp_manager/root.pem\n\n[auth]\nmethod=ldap\nuse_ssl=true\nldap_servers=dc.example.com\nbase_dn=DC=example,DC=com\ndefault_domain=example.com\njwt_algorithm=HS256\njwt_token_lifetime_mins=480\nadmin_group=pulpmaster-rw\nrequire_jwt_auth=true\n\n[pulp]\ndeb_signing_service=pulp_deb\nbanned_package_regex=bannedexample|another\ninternal_domains=example.com\ngit_repo_config=https://git.example.com/Pulp-Repo-Config\ngit_repo_config_dir=repo_config\npassword=password\ninternal_package_prefix=corp_\npackage_name_replacement_pattern=\npackage_name_replacement_rule=\nremote_tls_validation=true\nuse_https_for_sync=true\n\n[redis]\nhost=redis\nport=6379\ndb=0\nmax_page_size=24\n\n[remotes]\nsock_connect_timeout=120.0\nsock_read_timeout=600.0\n\n[paging]\ndefault_page_size=50\nmax_page_size=20000\n\n[vault]\nvault_addr=http://127.0.0.1:8200\nrepo_secret_namespace=secrets-common\n```\n\n### ca\n\nDefines Certificate Authority settings\n- `root_ca_file_path`: Path to root ca file, which is applied to\n  remotes that are synched over SSL\n\n### auth\n\nDefines authentication allowed against the API\n- `method`: Type of auth to use, currently only LDAP is allowed\n- `use_ssl`: Specifies if LDAPS should be used\n- `ldap_servers`: Comma separate list of LDAP servers to use for\n  authentication\n- `base_dn`: Base Distinguished Name to search for users in when\n  carrying out authentication\n- `default_domain`: Netbios name of the Active Directory domain\n- `jwt_algorithm`: Algorithm to use to encrypt JWT tokens\n- `jwt_token_lifetime_mins`: Number of minutes JWT is valid for\n- `admin_group`: Directory group user must be a member of to carry out\n  privileged actions against the API\n- `require_jwt_auth`: Boolean whether to require JWT authentication for\n  protected API endpoints. Set to false for local development environments\n  where authentication is not needed. Defaults to true\n\n### pulp\n\nSettings to apply to all pulp servers\n- `deb_signing_service`: Name of the signing service to use to sign\n  Release file of deb repos\n- `banned_package_regex`: Regex of packages that should be removed\n  from externally synched repos\n- `internal_domains`: Comma separated list of domains that are\n  internal. Defines when the root CA cert should be applied, along\n  with steps in synchronisation that can be synched when synching from\n  a Pulp Server\n- `git_repo_config`: Git repository URL that contains the\n  configuration files for Pulp repos that should exist on primary\n  servers\n- `git_repo_config_dir`: Directory in `git_repo_config` which contains\n  the pulp repo config\n- `remote_tls_validation`: Boolean whether to require TLS validation\n  of remote hosts\n- `use_https_for_sync`: Boolean whether to use HTTPS for repository sync URLs.\n  Set to false for local HTTP-only development environments. Defaults to true.\n\n### redis\n\nSettings to connect to redis\n- `host`: hostname of the redis server\n- `port`: port to connect to redis on\n- `db`: db number to use\n- `max_page_size`: Used via API to define maximum number of results\n  that can be pulled back from redis at once\n\n### remotes\n\nSettings to all remotes created/update by Pulp Manager\n- `sock_connect_timeout`: aiohttp.ClientTimeout.sock_connect (q.v.)\n  for download-connections\n- `sock_read_timeout`: aiohttp.ClientTimeout.sock_read (q.v.) for\n  download-connections\n\n### paging\n\nDefault settings for paging on the API\n- `default_page_size`: Default size of pages retrieved from API\n- `max_page_size`: Maximum number of results that can be returned in a\n  single page\n\n### vault\n\nSettings for how Pulp Manager interacts with the vault agent\n- `vault_addr`: Address to use to communicate with the vault agent\n- `repo_secret_namespace`: namespace which contains remote\n  secrets. This is where RedHat Certs and keys should be placed as\n  defined in the repo config at\n  https://git.example.com/Pulp-Repo-Config\n\n## Sync Configuration\n\nA YAML file needs to provided which the app reads on start up, to\ninsert the pulp servers and repo group information into the DB. File\nneeds to be deployed to /etc/pulp_manager/pulp_config.yml\n\nA sample configuration file is shown below:\n\n```\npulp_servers:\n  pulp3.example.com:\n    credentials: example\n    repo_config_registration:\n        schedule: \"0,15,30,45 * * * *\"\n        max_runtime: \"20m\"\n    repo_groups:\n      external_repos:\n        schedule: \"0 0 * * *\"\n        max_concurrent_sync: 2\n        max_runtime: \"6h\"\n    snapshot_support:\n      max_concurrent_snapshots: 2\n\n  pulp3slav1.example.com:\n    credentials: example\n    repo_groups:\n      external_repos:\n        schedule: \"0 6 * * *\"\n        max_concurrent_sync: 2\n        max_runtime: \"6h\"\n        pulp_master: pulp3mast1.example.com\n\ncredentials:\n  example:\n    username: svc-linux-pulp-dapi\n    vault_service_account_mount: service-accounts\n\nrepo_groups:\n  external_repos:\n    regex_include: ^ext-\n```\n\nThe different sections are as follows:\n\n### pulp_servers\n\nThis is a dict which contains the name of the pulp server that is to\nbe managed, with the value being a series of dicts that define the\ncredentials and repo groups to sync.\n\n- `credentials`: The name of the credentials block to use to retrieve\n  credentials from HashiCorp Vault for authenticating against the Pulp\n  Server API\n- `repo_config_registration`: This is for use with pulp\n  primaries. There is a Git repository which contains the base repos\n  we expect to have on Pulp Servers\n  (https://git.example.com/Pulp-Repo-Config). This repo defines remote\n  repos that are used to sync external repos for the OS release along\n  with internal repos. This parameter defines how often the config is\n  checked out from Git and re-applied to the pulp server\n  - `schedule`: cron syntax to define how often the job should run\n  - `max_runtime`: how long the job should run for before it is\n    cancelled\n- `repo_groups`: Defines groups of repos that should be synched on a\n  regular basis. The key is name of the repo group block to sync and\n  the value is another dict which contains the options to use carrying\n  out the syncs\n  - `schedule`: cron syntax for how often the repo group should be\n    synched\n  - `max_concurrent_syncs`: How many repos should be synched at once\n    when the job is run\n  - `max_runtime`: How long the job should run for before it is\n    cancelled\n  - `pulp_master` (Optional): If the pulp server is synching the\n    repos from a pulp primary, specify the name of the pulp\n    server. This needs to exist in the pulp_servers config so that the\n    list of repos on the server can be retrieved via the API\n- `snapshot_support`: specifies if snapshots can be run against the\n  pulp server, value is a dict\n  - `max_concurrent_snapshots`: number of repos that can snapshotted\n    simultaneously\n\n### credentials\n\nThis is a dict which defines the name of credentials groups. The key\nis a dict which names the credential group and the value, is another\ndict which contains the configuration that pulp manager users to\nretrieve the credentials from HashiCorp vault\n\n- `username`: username of credentials group to retrieve\n- `vault_service_account_mount`: vault service account path to\n  retrieve the credentials form e.g. service-accounts\n### repo_groups\n\nThis is a dict which defines a name for a set of repos, and then\nregular expressions to match repo names on. The repo groups are then\napplied to pulp server, which schedules and run times can be specified\n\n- `regex_include` (Optional): regex to match repo names on that should\n  be included for synchronisation\n- `regex_exclude` (Optional): regex to match repo names that should be\n  excluded from synchronisation. `regex_exclude` take precedence over\n  `regex_include`, so if there is a repo that matches both regexes it\n  would be excluded\n\n## Example Repository Configuration\n\nRepository configurations are stored in a Git repository and are\ndefined as JSON files. Here's an example structure:\n\n### External Repository (e.g., CentOS):\n```json\n{\n  \"name\": \"centos-base\",\n  \"content_repo_type\": \"rpm\",\n  \"description\": \"CentOS 7 Base Repository\",\n  \"owner\": \"Core Linux Engineering\",\n  \"base_url\": \"centos7-x86_64\",\n  \"url\": \"http://mirror.centos.org/centos/7/os/x86_64/\",\n  \"proxy\": \"http://proxy.example.com:8080\",\n  \"tls_validation\": true\n}\n```\n\n### Internal Repository:\n```json\n{\n  \"name\": \"myapp\",\n  \"content_repo_type\": \"deb\",\n  \"description\": \"Internal Application Packages\",\n  \"owner\": \"Application Team\",\n  \"base_url\": \"ubuntu-20.04-x86_64\"\n}\n```\n\nRepository names are automatically prefixed:\n- External repos (with \"url\" field): get \"ext-\" prefix\n- Internal repos: get the configured internal package prefix\n\n## Local Development\n\n### Prerequisites\n\n- Docker and Docker Compose\n- Python 3.10+ (for local development without containers)\n- Git\n- 8GB RAM minimum (for running all services)\n- Visual Studio Code with Dev Containers extension (for DevContainer\n  development)\n\n### Development with DevContainers (Recommended)\n\nThis project includes a DevContainer configuration for consistent\ndevelopment environments across different machines. DevContainers\nprovide a fully configured development environment with all necessary\ndependencies, services, and tools pre-installed.\n\n#### Getting Started with DevContainers\n\n1. **Using VS Code (Recommended)**\n   - Open the project in VS Code\n   - When prompted, click \"Reopen in Container\"\n   - Or use Command Palette (F1) → \"Dev Containers: Reopen in\n     Container\"\n   - VS Code will build and start the container with all services\n\n2. **Using Command Line**\n   ```bash\n   # Install devcontainer CLI\n   npm install -g @devcontainers/cli\n   \n   # Open in devcontainer\n   devcontainer open\n   ```\n\nThe DevContainer includes:\n- Python 3.10 with all project dependencies\n- MariaDB 11.1.2 for the database\n- Redis for caching and task queuing\n- LDAP development libraries\n- Pre-configured pytest with VS Code integration\n- All required Python packages from requirements.txt\n\n#### Running Tests in DevContainer\n\nOnce inside the DevContainer:\n```bash\n# Run all tests\nmake t\n\n# Run with coverage\nmake c\n\n# Run specific test file\n./venv/bin/pytest pulp_manager/tests/unit/test_job_manager.py -v\n\n# Run lint\nmake l\n```\n\n### Alternative: Manual Development Setup\n\nIf you prefer not to use DevContainers, you can set up the development\nenvironment manually:\n\n1. **Starting the Development Environment**\n\nTo initialize and start the services required for local development,\nexecute the following command in your terminal:\n\n```shell\nmake run-pulp-manager\n```\nThis command starts the Pulp Manager API, worker, and RQ dashboard services along with their dependencies (MariaDB and Redis). It uses the demo/docker-compose.yml configuration. \n\nFor local authentication, the Pulp manager utilizes the password\nspecified for pulp3 in local_config.ini and the username defined in\nlocal_pulp_config.yml. Note that this configuration is contingent upon\nthe is_local environment variable being set to true. (This can be\nfound in pulp_helpers.py)\n\n2. **Port Forwarding (Manual Setup Only)**\n\nIf using the manual setup, forward port 8080 from your environment to\nyour local machine. With DevContainers, ports are automatically\nforwarded as configured in devcontainer.json.\n\nFor manual setups or DevPods:\n```shell\ndevpod tunnel \u003cname of your devpod\u003e -p 8080:8080\n```\n\n3. **Accessing the Application**  \n\nOnce the development environment is up, you can access the application\nthrough your web browser. Navigate to:\n\n```\nhttp://localhost:8080/docs\n```\n\n**Note**: With DevContainers, VS Code automatically handles port\nforwarding for ports 8080, 9300, 3306, and 6379 as configured in the\ndevcontainer.json.\n4. **Hot Reloading**  \n\nThe development environment is configured to support hot\nreloading. This feature automatically refreshes your application as\nsoon as you make and save changes to the code. This means there's no\nneed to stop and restart the entire environment every time you modify\na file.\n\n\n5. **Starting Pulp 3 Environment**\n\nFor development that requires Pulp 3, you can start the Pulp 3 environment. Run the following command in your terminal:\n```\nmake run-pulp3\n```\nThis command starts the Pulp 3 primary and secondary servers using the demo/docker-compose.yml configuration. It's particularly useful for testing integrations with Pulp 3 or when working on features that depend on Pulp 3 services.\n\n#### When to Use make run-pulp-manager Again:\n\n**Modifying Dependencies**: If your changes involve updating, adding,\nor removing dependencies in your project, you will need to re-run the\nmake run-pulp-manager command. This ensures that the new dependencies\nare correctly installed and integrated into your development\nenvironment.\n\n**Major Configuration Changes**: Similarly, for major changes to the\nDocker configuration or other integral parts of the development setup\nthat are not automatically applied through hot reloading, re-running\nmake run-pulp-manager is necessary.\n\n## Coding Style and Linters\n\nOur coding standards and tools:\n\n- **Coding Standards**: Follow existing code patterns in the\n  codebase. Use repository pattern for data access, service layer for\n  business logic, and dependency injection.\n- **Linters**: We use pylint for Python code quality checks. Run with\n  `make lint`.\n\n## Branching Model\n\nWe use GitHub Flow with feature branches. Create a feature branch from\nmain, make your changes, and submit a pull request back to main.\n\n## Contributing\n\nPlease read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our\ndevelopment workflow, coding standards, and how to submit pull\nrequests.\n\nPlease read [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for details on\nour code of conduct.\n\n### Development Workflow\n1. Fork the repository\n2. Create a feature branch (`git checkout -b amazing-feature`)\n3. Make your changes\n4. Run tests (`make t`)\n5. Commit your changes following conventional commits\n6. Push to your fork\n7. Open a Pull Request\n\n### Running Tests\n```bash\n# Run all tests\nmake t\n\n# Run with coverage\nmake c\n\n# Run linting\nmake l\n```\n\n## Codeowners\n\nFor details on code ownership and project maintainers, please see the\n[MAINTAINERS.md](MAINTAINERS.md) file.\n\n## Community\n\nFor development support and community discussions, please use:\n- GitHub Issues: https://github.com/G-Research/Pulp-manager/issues\n- GitHub Discussions:\n  https://github.com/G-Research/Pulp-manager/discussions\n\n## Community Guidelines\n\nPlease read [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for details on\nacceptable conduct and community engagement guidelines.\n\n## Governance\n\nThis project is governed by G-Research. For detailed governance\ninformation, please see [GOVERNANCE.md](GOVERNANCE.md) if available.\n\n## Continuous Integration\n\nThis project uses GitHub Actions for CI/CD with DevContainer\nintegration:\n\n- **Automated Testing**: All tests run in the same DevContainer\n  environment used for development\n- **Linting**: Code quality checks with pylint\n- **Coverage Reporting**: Test coverage analysis with pytest-cov\n- **Multiple Test Strategies**: Both direct pytest and `make t`\n  execution\n\nThe CI workflows are defined in `.github/workflows/`:\n- `ci.yml`: Comprehensive CI with linting, testing, and coverage\n  reporting\n\nSee `.github/workflows/README.md` for detailed workflow documentation.\n\n## Troubleshooting\n\n### Common Issues\n\n1. **DevContainer fails to start**\n   - Ensure Docker is running\n   - Check port conflicts (8080, 3306, 6379)\n   - Try: `docker system prune` to clean up resources\n\n2. **Tests failing with database errors**\n   - Database migrations may be needed\n   - Run: `docker exec \u003ccontainer\u003e alembic upgrade head`\n\n3. **Authentication issues**\n   - Check LDAP configuration in config.ini\n   - Verify group membership matches `admin_group` setting\n\n4. **Import errors in tests**\n   - Ensure all dependencies are installed: `pip install -r\n     requirements.txt`\n   - Check that pulp3_bindings is installed: `pip install -e\n     ./pulp3_bindings`\n\nFor more help, see\n[Issues](https://github.com/G-Research/Pulp-manager/issues)\n\n## Feedback\n\nTo provide feedback or report issues:\n- **Bug Reports**: Please file bug reports at\n  https://github.com/G-Research/Pulp-manager/issues\n- **Feature Requests**: Submit feature requests at\n  https://github.com/G-Research/Pulp-manager/issues\n- **General Discussion**: Use GitHub Discussions at\n  https://github.com/G-Research/Pulp-manager/discussions\n\n## Glossary\n\n- **Pulp**: Content management platform for software repositories\n- **Pulp Primary**: Main Pulp server that syncs from external sources. Formerly known as Pulp master.\n- **Pulp Secondary**: Pulp server that syncs from the primary. Formerly known as Pulp slave.\n- **RQ**: Redis Queue - Python job queue library\n- **LDAP**: Lightweight Directory Access Protocol for authentication\n- **JWT**: JSON Web Token for API authentication\n- **DevContainer**: Development environment configuration for VS Code\n\n## License\n\nThis project is licensed under the Apache 2.0 License - see the\n[LICENSE](LICENSE) file for details.\n\nSPDX-License-Identifier: Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpulp%2Fpulp-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpulp%2Fpulp-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpulp%2Fpulp-manager/lists"}