Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: plugins downloader #168

Merged
merged 26 commits into from Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Expand Up @@ -56,7 +56,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-22.04, windows-latest]
python-version: ["3.8", "3.9", "3.10"]
python-version: ["3.8", "3.9", "3.10", "3.11"]

runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Expand Up @@ -36,7 +36,7 @@
"python.testing.pytestEnabled": true,
// extensions
"autoDocstring.guessTypes": true,
"autoDocstring.docstringFormat": "one-line-sphinx",
"autoDocstring.docstringFormat": "google",
"autoDocstring.generateDocstringOnEnter": false,
"yaml.schemas": {
"docs/schemas/schema.json": "tests/fixtures/scenarios/*.qdt.yml",
Expand Down
1 change: 1 addition & 0 deletions docs/jobs/index.md
Expand Up @@ -5,5 +5,6 @@
caption: Jobs
maxdepth: 1
---
plugins_manager.md
splash_screen_manager.md
```
105 changes: 105 additions & 0 deletions docs/jobs/plugins_manager.md
@@ -0,0 +1,105 @@
# Plugins manager

This job download plugins into QDT local folder and synchronize them with installed profiles.

----

## Use it

Sample job configuration in your scenario file:

```yaml
- name: Synchronize plugins
uses: qplugins-manager
with:
action: create_or_restore
```

----

## Options

### action

Tell the job what to do with plugins in **installed profiles**:

Possible_values:

- `create`: add plugins if they are not present
- `create_or_restore`: add plugins if not present and replace eventual existing one
- `remove`: remove plugins which are not listed

### force

Controls download mode.

Possible_values:

- `false` (_default_): download only plugins which are not present into the local QDT folder
- `true`: download every plugin referenced in profile.json files into the local QDT folder, even if the archive is already here

### threads

Number of threads to use for downloading.

Possible_values:

- `1`: do not use multi-thread but download plugins synchroneously
- `2`, `3`, `4` or `5` (_default_): number of threads to parallelize plugins download

----

## How does it work

### Specify the file to use in the `profile.json`

Add the image file to the profile folder and specify the relative filepath under the `splash` attribute:

```json
{
[...]
"plugins": [
{
"name": "french_locator_filter",
"version": "1.0.4",
"official_repository": true,
},
{
"name": "pg_metadata",
"version": "1.2.1",
"url": "https://plugins.qgis.org/plugins/pg_metadata/version/1.2.1/download/",
"location": "remote",
"official_repository": true,
},
{
"name": "Geotuileur",
"version": "1.0.0",
"url": "https://oslandia.gitlab.io/qgis/ign-geotuileur/geotuileur.1.0.0.zip",
"location": "remote",
"official_repository": false,
"repository_url_xml": "https://oslandia.gitlab.io/qgis/ign-geotuileur/plugins.xml"
}
[...]
}
```

### Store the image file under the default path

If the path is not specified into the `profile.json`, the job looks for the default filepath `images/splash.png`. If the file exists, it will be used as splash screen image.

### Workflow

1. Create a subfolder `plugins` into the local QDT working directory. Default: `~/.cache/qgis-deployment-toolbelt/plugins`
1. Parse profiles downloaded by QDT (not the installed)
1. Create an unified list of used plugins
1. Download, if not already existing, every plugin into the plugins subfolder with this structure: `plugins/{plugin-name-slufigied}/{plugin-version}/{plugin-name-version}.zip`
1. Unzip plugins in installed profiles

```mermaid
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
```
9 changes: 5 additions & 4 deletions qgis_deployment_toolbelt/cli.py
Expand Up @@ -20,6 +20,7 @@
# submodules
from qgis_deployment_toolbelt.__about__ import __version__
from qgis_deployment_toolbelt.commands import cli_check, cli_clean, cli_upgrade
from qgis_deployment_toolbelt.constants import get_qdt_working_directory
from qgis_deployment_toolbelt.jobs import JobsOrchestrator
from qgis_deployment_toolbelt.scenarios import ScenarioReader
from qgis_deployment_toolbelt.utils.bouncer import exit_cli_error, exit_cli_normal
Expand Down Expand Up @@ -123,10 +124,6 @@ def qgis_deployment_toolbelt(
if result_scenario_validity is not None:
exit_cli_error(result_scenario_validity)

# let's be clear or not
if clear:
click.clear()

# -- LOG/VERBOSITY MANAGEMENT ------------------------------------------------------
# if verbose, override conf value
if verbose:
Expand Down Expand Up @@ -172,6 +169,10 @@ def qgis_deployment_toolbelt(
else:
logger.debug(f"Ignored None value: {var}.")

logger.info(
f"QDT working folder: {get_qdt_working_directory(specific_value=scenario.settings.get('LOCAL_QDT_WORKDIR'), identifier=scenario.metadata.get('id'))}"
)

# -- STEPS JOBS
steps_ok = []
orchestrator = JobsOrchestrator()
Expand Down
1 change: 0 additions & 1 deletion qgis_deployment_toolbelt/commands/cli_upgrade.py
Expand Up @@ -31,7 +31,6 @@
exit_cli_success,
)
from qgis_deployment_toolbelt.utils.file_downloader import download_remote_file_to_local
from qgis_deployment_toolbelt.utils.slugger import sluggy

# #############################################################################
# ########## Globals ###############
Expand Down
42 changes: 40 additions & 2 deletions qgis_deployment_toolbelt/constants.py
Expand Up @@ -14,8 +14,9 @@
# Standard library
import logging
from dataclasses import dataclass
from os import getenv
from os.path import expandvars
from functools import lru_cache
from os import PathLike, getenv
from os.path import expanduser, expandvars
from pathlib import Path
from typing import Tuple

Expand All @@ -26,6 +27,43 @@
# logs
logger = logging.getLogger(__name__)

# #############################################################################
# ########## Functions #############
# ##################################


@lru_cache(maxsize=128)
def get_qdt_working_directory(
specific_value: PathLike = None, identifier: str = "default"
) -> Path:
"""Get QDT working directory.

Args:
specific_value (PathLike, optional): a specific path to use. If set it's \
expanded and returned. Defaults to None.
identifier (str, optional): used to make the folder unique. If not set, \
'default' (sure, not so unique...) is used. Defaults to None.

Returns:
Path: path to the QDT working directory
"""
if specific_value:
return Path(expandvars(expanduser(specific_value)))
elif getenv("QDT_PROFILES_PATH"):
return Path(expandvars(expanduser(getenv("QDT_PROFILES_PATH"))))
else:
return Path(
expandvars(
expanduser(
getenv(
"LOCAL_QDT_WORKDIR",
f"~/.cache/qgis-deployment-toolbelt/{identifier}",
),
)
)
)


# #############################################################################
# ########## Classes ###############
# ##################################
Expand Down