|
7 | 7 | import os |
8 | 8 | import re |
9 | 9 | import sys |
| 10 | +import traceback |
| 11 | +import requests |
| 12 | +import toml |
| 13 | + |
10 | 14 | from dataclasses import dataclass |
11 | 15 | from enum import Enum, auto |
12 | 16 | from importlib import metadata |
13 | 17 | from pathlib import Path |
14 | 18 | from urllib.parse import urljoin, urlparse |
15 | | - |
16 | | -import requests |
17 | | -import toml |
18 | 19 | from pydantic import BaseModel |
19 | 20 | from requests import HTTPError |
20 | 21 |
|
@@ -174,6 +175,18 @@ def __init__(self, parser: argparse.ArgumentParser): |
174 | 175 | "deposit_extra_files": "", |
175 | 176 | "push_branch": "main" |
176 | 177 | } |
| 178 | + self.hermes_toml_data = { |
| 179 | + "harvest": { |
| 180 | + "sources": ["cff"] |
| 181 | + }, |
| 182 | + "deposit": { |
| 183 | + "target": "invenio_rdm", |
| 184 | + "invenio_rdm": { |
| 185 | + "site_url": "", |
| 186 | + "access_right": "open" |
| 187 | + } |
| 188 | + } |
| 189 | + } |
177 | 190 | self.plugin_relevant_commands = ["harvest", "deposit"] |
178 | 191 | self.builtin_plugins: dict[str: HermesPlugin] = get_builtin_plugins(self.plugin_relevant_commands) |
179 | 192 | self.selected_plugins: list[marketplace.PluginInfo] = [] |
@@ -210,40 +223,51 @@ def __call__(self, args: argparse.Namespace) -> None: |
210 | 223 | if args.template_branch != "": |
211 | 224 | self.template_branch = args.template_branch |
212 | 225 |
|
213 | | - # Test if init is valid in current folder |
214 | | - self.test_initialization() |
| 226 | + try: |
| 227 | + # Test if init is valid in current folder |
| 228 | + self.test_initialization() |
| 229 | + |
| 230 | + sc.echo(f"Starting to initialize HERMES in {self.folder_info.absolute_path}\n") |
| 231 | + sc.max_steps = 8 |
215 | 232 |
|
216 | | - sc.echo(f"Starting to initialize HERMES in {self.folder_info.absolute_path}") |
217 | | - sc.max_steps = 8 |
| 233 | + sc.next_step("Configure HERMES plugins") |
| 234 | + self.choose_plugins() |
| 235 | + self.integrate_plugins() |
218 | 236 |
|
219 | | - sc.next_step("Configure HERMES plugins") |
220 | | - self.choose_plugins() |
| 237 | + sc.next_step("Configure deposition platform and setup method") |
| 238 | + self.choose_deposit_platform() |
| 239 | + self.integrate_deposit_platform() |
| 240 | + self.choose_setup_method() |
221 | 241 |
|
222 | | - sc.next_step("Configure deposition platform and setup method") |
223 | | - self.choose_deposit_platform() |
224 | | - self.choose_setup_method() |
| 242 | + sc.next_step("Configure HERMES behaviour") |
| 243 | + self.choose_push_branch() |
| 244 | + self.choose_deposit_files() |
225 | 245 |
|
226 | | - sc.next_step("Configure HERMES behaviour") |
227 | | - self.choose_push_branch() |
228 | | - self.choose_deposit_files() |
| 246 | + sc.next_step("Create hermes.toml file") |
| 247 | + self.create_hermes_toml() |
229 | 248 |
|
230 | | - sc.next_step("Create hermes.toml file") |
231 | | - self.create_hermes_toml() |
| 249 | + sc.next_step("Create CITATION.cff file") |
| 250 | + self.create_citation_cff() |
232 | 251 |
|
233 | | - sc.next_step("Create CITATION.cff file") |
234 | | - self.create_citation_cff() |
| 252 | + sc.next_step("Create git CI files") |
| 253 | + self.update_gitignore() |
| 254 | + self.create_ci_template() |
235 | 255 |
|
236 | | - sc.next_step("Create git CI files") |
237 | | - self.update_gitignore() |
238 | | - self.create_ci_template() |
| 256 | + sc.next_step("Connect with deposition platform") |
| 257 | + self.connect_deposit_platform() |
239 | 258 |
|
240 | | - sc.next_step("Connect with deposition platform") |
241 | | - self.connect_deposit_platform() |
| 259 | + sc.next_step("Connect with git hoster") |
| 260 | + self.configure_git_project() |
242 | 261 |
|
243 | | - sc.next_step("Connect with git hoster") |
244 | | - self.configure_git_project() |
| 262 | + sc.echo("\nHERMES is now initialized and ready to be used.\n", |
| 263 | + formatting=sc.Formats.OKGREEN+sc.Formats.BOLD) |
245 | 264 |
|
246 | | - sc.echo("\nHERMES is now initialized and ready to be used.\n", formatting=sc.Formats.OKGREEN+sc.Formats.BOLD) |
| 265 | + except Exception as e: |
| 266 | + # More useful message on error |
| 267 | + sc.echo(f"An error occurred during execution of HERMES init: {e}", |
| 268 | + formatting=sc.Formats.FAIL+sc.Formats.BOLD) |
| 269 | + sc.debug_info(traceback.format_exc()) |
| 270 | + sys.exit(2) |
247 | 271 |
|
248 | 272 | def test_initialization(self) -> None: |
249 | 273 | """Test if init is possible and wanted. If not: sys.exit()""" |
@@ -284,6 +308,7 @@ def test_initialization(self) -> None: |
284 | 308 | if self.git_remote: |
285 | 309 | self.git_remote_url = git_info.get_remote_url(self.git_remote) |
286 | 310 | self.git_hoster = get_git_hoster_from_url(self.git_remote_url) |
| 311 | + |
287 | 312 | # Abort with no remote |
288 | 313 | else: |
289 | 314 | sc.echo("Your git project does not have a remote. It is recommended for HERMES to " |
@@ -311,26 +336,12 @@ def test_initialization(self) -> None: |
311 | 336 | sys.exit() |
312 | 337 |
|
313 | 338 | def create_hermes_toml(self) -> None: |
314 | | - """Creates the hermes.toml file based on a dictionary""" |
315 | | - deposit_url = DepositPlatformUrls.get(self.deposit_platform) |
316 | | - default_values = { |
317 | | - "harvest": { |
318 | | - "sources": ["cff"] |
319 | | - }, |
320 | | - "deposit": { |
321 | | - "target": "invenio_rdm", |
322 | | - "invenio_rdm": { |
323 | | - "site_url": deposit_url, |
324 | | - "access_right": "open" |
325 | | - } |
326 | | - } |
327 | | - } |
328 | | - |
| 339 | + """Creates the hermes.toml file based on a self.hermes_toml_data""" |
329 | 340 | if (not self.folder_info.has_hermes_toml) \ |
330 | 341 | or sc.confirm("Do you want to replace your `hermes.toml` with a new one?", default=True): |
331 | 342 | with open('hermes.toml', 'w') as toml_file: |
332 | 343 | # noinspection PyTypeChecker |
333 | | - toml.dump(default_values, toml_file) |
| 344 | + toml.dump(self.hermes_toml_data, toml_file) |
334 | 345 | sc.echo("`hermes.toml` was created.", formatting=sc.Formats.OKGREEN) |
335 | 346 |
|
336 | 347 | def create_citation_cff(self) -> None: |
@@ -384,7 +395,6 @@ def create_ci_template(self) -> None: |
384 | 395 | """Downloads and configures the ci workflow files using templates from the chosen template branch.""" |
385 | 396 | match self.git_hoster: |
386 | 397 | case GitHoster.GitHub: |
387 | | - # TODO Replace this later with the link to the real templates (not the feature branch) |
388 | 398 | template_url = self.get_template_url("TEMPLATE_hermes_github_to_zenodo.yml") |
389 | 399 | ci_file_folder = ".github/workflows" |
390 | 400 | ci_file_name = "hermes_github.yml" |
@@ -429,10 +439,11 @@ def configure_ci_template(self, ci_file_path) -> None: |
429 | 439 | parameters = list(set(re.findall(r'{%(.*?)%}', content))) |
430 | 440 | for parameter in parameters: |
431 | 441 | if parameter in self.ci_parameters: |
432 | | - content = content.replace(f'{{%{parameter}%}}', self.ci_parameters[parameter]) |
| 442 | + value = str(self.ci_parameters[parameter]) |
| 443 | + content = content.replace(f'{{%{parameter}%}}', value) |
433 | 444 | else: |
434 | | - sc.echo(f"Warning: CI File Parameter {{%{parameter}%}} was not set.", |
435 | | - formatting=sc.Formats.WARNING) |
| 445 | + sc.debug_info(f"CI File Parameter {{%{parameter}%}} was not set.", formatting=sc.Formats.WARNING) |
| 446 | + content = content.replace(f'{{%{parameter}%}}', '') |
436 | 447 | with open(ci_file_path, 'w') as file: |
437 | 448 | file.write(content) |
438 | 449 |
|
@@ -572,6 +583,11 @@ def choose_deposit_platform(self) -> None: |
572 | 583 | ) |
573 | 584 | self.deposit_platform = deposit_platform_list[deposit_platform_index] |
574 | 585 |
|
| 586 | + def integrate_deposit_platform(self) -> None: |
| 587 | + """Makes changes to the toml data or something else based on the chosen deposit platform.""" |
| 588 | + deposit_url = DepositPlatformUrls.get(self.deposit_platform) |
| 589 | + self.hermes_toml_data["deposit"]["invenio_rdm"]["site_url"] = deposit_url |
| 590 | + |
575 | 591 | def choose_setup_method(self) -> None: |
576 | 592 | """User chooses his desired setup method: Either preferring automatic (if available) or manual.""" |
577 | 593 | setup_method_index = sc.choose( |
@@ -615,18 +631,42 @@ def choose_plugins(self): |
615 | 631 | sc.echo("The following plugins are available for installation:") |
616 | 632 | for info in plugins_available: |
617 | 633 | sc.echo(str(info), formatting=sc.Formats.WARNING, no_log=True) |
| 634 | + if info.abstract: |
| 635 | + sc.echo("-> " + info.abstract, formatting=sc.Formats.ITALIC+sc.Formats.WARNING, no_log=True) |
618 | 636 | sc.echo("") |
619 | 637 | else: |
620 | 638 | self.selected_plugins = plugins_selected |
621 | 639 | break |
622 | | - choice = sc.choose("Do you want to add a plugin?", ["No"] + [p.name for p in plugins_available]) |
| 640 | + no_text = "No further plugins needed" |
| 641 | + choice = sc.choose("Do you want to add a plugin?", |
| 642 | + [no_text] + [f"Add {p.name}" for p in plugins_available]) |
623 | 643 | if choice == 0: |
624 | 644 | self.selected_plugins = plugins_selected |
625 | 645 | break |
626 | 646 | else: |
627 | 647 | chosen_plugin = plugins_available.pop(choice - 1) |
628 | 648 | plugins_selected.append(chosen_plugin) |
629 | 649 |
|
| 650 | + def integrate_plugins(self): |
| 651 | + """ |
| 652 | + Plugin installation is added to the ci-parameters. |
| 653 | + Also for now we use this method to do custom plugin installation steps. |
| 654 | + """ |
| 655 | + for plugin_info in self.selected_plugins: |
| 656 | + if not plugin_info.is_valid(): |
| 657 | + sc.echo(f"Could not install plugin: {plugin_info.name}", formatting=sc.Formats.FAIL) |
| 658 | + continue |
| 659 | + pip_install = plugin_info.get_pip_install_command() |
| 660 | + self.ci_parameters["pip_install_plugins_github"] = \ |
| 661 | + self.ci_parameters.get("pip_install_plugins_github", "") + " - run: " + pip_install + "\n" |
| 662 | + self.ci_parameters["pip_install_plugins_gitlab"] = \ |
| 663 | + self.ci_parameters.get("pip_install_plugins_gitlab", "") + " - " + pip_install + "\n" |
| 664 | + match plugin_info.name: |
| 665 | + case "hermes-plugin-python": |
| 666 | + self.hermes_toml_data["harvest"]["sources"].append("toml") |
| 667 | + case "hermes-plugin-git": |
| 668 | + self.hermes_toml_data["harvest"]["sources"].append("git") |
| 669 | + |
630 | 670 | def no_git_setup(self, start_question: str = "") -> None: |
631 | 671 | """Makes the init for a gitless project (basically just creating hermes.toml)""" |
632 | 672 | if start_question == "": |
|
0 commit comments