Jürgen Gmach has proposed merging ~jugmac00/lpcraft:provide-additional-repositories-via-cli into lpcraft:main.
Commit message: Clean up CLI documentation Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~jugmac00/lpcraft/+git/lpcraft/+merge/428089 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~jugmac00/lpcraft:provide-additional-repositories-via-cli into lpcraft:main.
diff --git a/NEWS.rst b/NEWS.rst index 75f4484..5dcd320 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -8,6 +8,8 @@ Version history - Add input properties, allowing jobs to use artifacts built by previous pipeline stages. +- Enable providing additional repositories via CLI. + 0.0.24 (2022-08-05) =================== diff --git a/docs/cli-interface.rst b/docs/cli-interface.rst index 0c44c3f..38a98f1 100644 --- a/docs/cli-interface.rst +++ b/docs/cli-interface.rst @@ -20,15 +20,19 @@ lpcraft run optional arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``--apt-replace-repositories SOURCE_LINE``, e.g. - ``lpcraft run --apt-replace-repositories "deb http://archive.ubuntu.com/ubuntu/ focal main restricted"``. - Please note that the option is repeatable. + ``lpcraft run --apt-replace-repositories "deb http://archive.ubuntu.com/ubuntu/ focal main restricted"`` -- ``--set-env KEY=VALUE``, e.g. - ``lpcraft run --set-env="PIP_INDEX_URL=http://pypi.example.com/simple"`` + This option is repeatable. + +- ``--package-repository`` (provide an additional repository), e.g. + ``lpcraft run --package-repository "deb http://archive.ubuntu.com/ubuntu/ focal main restricted"`` + This option is repeatable. - ``--plugin-setting``, e.g. ``lpcraft run --plugin-setting="foo=bar"`` + This option is repeatable. + - ``--secrets``, e.g. ``lpcraft run --secrets="<path-to-configuration-file>"`` @@ -39,6 +43,10 @@ lpcraft run optional arguments key: secret another_key: another_secret +- ``--set-env KEY=VALUE``, e.g. + ``lpcraft run --set-env="PIP_INDEX_URL=http://pypi.example.com/simple"`` + + This option is repeatable. lpcraft run-one --------------- @@ -55,17 +63,21 @@ lpcraft run-one optional arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``--apt-replace-repositories SOURCE_LINE``, e.g. - ``lpcraft run-one --apt-replace-repositories "deb http://archive.ubuntu.com/ubuntu/ focal main restricted" test 0``. - Please note that the option is repeatable. + ``lpcraft run-one --apt-replace-repositories "deb http://archive.ubuntu.com/ubuntu/ focal main restricted" test 0`` -- ``--set-env KEY=VALUE``, e.g. - ``lpcraft run-one --set-env="PIP_INDEX_URL=http://pypi.example.com/simple" test 0``. + This option is repeatable. + +- ``--package-repository`` (provide an additional repository), e.g. + ``lpcraft run-one --package-repository "deb http://archive.ubuntu.com/ubuntu/ focal main restricted" test 0`` + This option is repeatable. - ``--plugin-setting``, e.g. - ``lpcraft run-one --plugin-setting="foo=bar" test 0``. + ``lpcraft run-one --plugin-setting="foo=bar" test 0`` + + This option is repeatable. - ``--secrets``, e.g. - ``lpcraft run-one --secrets="<path-to-configuration-file>" test 0``. + ``lpcraft run-one --secrets="<path-to-configuration-file>" test 0`` The configuration file should look like... @@ -73,3 +85,8 @@ lpcraft run-one optional arguments key: secret another_key: another_secret + +- ``--set-env KEY=VALUE``, e.g. + ``lpcraft run-one --set-env="PIP_INDEX_URL=http://pypi.example.com/simple" test 0`` + + This option is repeatable. diff --git a/lpcraft/commands/run.py b/lpcraft/commands/run.py index f485601..d8ed3d1 100644 --- a/lpcraft/commands/run.py +++ b/lpcraft/commands/run.py @@ -21,7 +21,7 @@ from jinja2 import BaseLoader, Environment from pluggy import PluginManager from lpcraft import env -from lpcraft.config import Config, Input, Job, Output, PackageRepository +from lpcraft.config import Config, Input, Job, Output from lpcraft.errors import CommandError from lpcraft.plugin.manager import get_plugin_manager from lpcraft.plugins import PLUGINS @@ -291,11 +291,11 @@ def _install_apt_packages( host_architecture: str, remote_cwd: Path, apt_replacement_repositories: Optional[List[str]], - additional_apt_repositories: Optional[List[PackageRepository]], + package_repositories: List[str], environment: Optional[Dict[str, Optional[str]]], secrets: Optional[Dict[str, str]], ) -> None: - if apt_replacement_repositories or additional_apt_repositories: + if apt_replacement_repositories or package_repositories: sources_list_path = "/etc/apt/sources.list" with NamedTemporaryFile(mode="w+") as tmpfile: @@ -310,9 +310,8 @@ def _install_apt_packages( if apt_replacement_repositories: sources = "\n".join(apt_replacement_repositories) + "\n" - if additional_apt_repositories: - for repository in additional_apt_repositories: - sources += "\n" + "\n".join(repository.sources_list_lines()) + if package_repositories: + sources += "\n" + "\n".join(package_repositories) if secrets: template = Environment(loader=BaseLoader()).from_string( sources @@ -406,8 +405,8 @@ def _run_job( job_index: int, provider: Provider, output: Optional[Path], - apt_replacement_repositories: Optional[List[str]] = None, - additional_apt_repositories: Optional[List[PackageRepository]] = None, + apt_replacement_repositories: Optional[List[str]], + package_repositories: List[str], env_from_cli: Optional[List[str]] = None, plugin_settings: Optional[List[str]] = None, secrets: Optional[Dict[str, str]] = None, @@ -500,7 +499,7 @@ def _run_job( host_architecture=host_architecture, remote_cwd=remote_cwd, apt_replacement_repositories=apt_replacement_repositories, - additional_apt_repositories=additional_apt_repositories, + package_repositories=package_repositories, environment=environment, secrets=secrets, ) @@ -606,6 +605,13 @@ class RunCommand(BaseCommand): type=Path, help="Pass in a YAML-based configuration file for secrets.", ) + parser.add_argument( + "--package-repository", + action="append", + default=[], + dest="package_repositories", + help="Provide an additional package repository.", + ) def run(self, args: Namespace) -> int: """Run the command.""" @@ -635,6 +641,11 @@ class RunCommand(BaseCommand): launched_instances.append( _get_job_instance_name(provider, job) ) + package_repositories = [] + for group in job.package_repositories: + for repository in group.sources_list_lines(): + package_repositories.append(repository) + package_repositories += args.package_repositories _run_job( config, job_name, @@ -644,7 +655,7 @@ class RunCommand(BaseCommand): apt_replacement_repositories=( args.apt_replace_repositories ), - additional_apt_repositories=job.package_repositories, # noqa: E501 + package_repositories=package_repositories, # noqa: E501 env_from_cli=args.set_env, plugin_settings=args.plugin_setting, secrets=secrets, @@ -737,6 +748,13 @@ class RunOneCommand(BaseCommand): type=Path, help="Pass in a YAML-based configuration file for secrets.", ) + parser.add_argument( + "--package-repository", + action="append", + default=[], + dest="package_repositories", + help="Provide an additional package repository.", + ) def run(self, args: Namespace) -> int: """Run the command.""" @@ -759,6 +777,11 @@ class RunOneCommand(BaseCommand): with open(args.secrets_file) as f: content = f.read() secrets = yaml.safe_load(content) + package_repositories = [] + for group in job.package_repositories: + for repository in group.sources_list_lines(): + package_repositories.append(repository) + package_repositories += args.package_repositories try: _run_job( config, @@ -767,7 +790,7 @@ class RunOneCommand(BaseCommand): provider, args.output_directory, apt_replacement_repositories=args.apt_replace_repositories, - additional_apt_repositories=job.package_repositories, + package_repositories=package_repositories, env_from_cli=args.set_env, plugin_settings=args.plugin_setting, secrets=secrets, diff --git a/lpcraft/commands/tests/test_run.py b/lpcraft/commands/tests/test_run.py index c60e0d7..9940c5b 100644 --- a/lpcraft/commands/tests/test_run.py +++ b/lpcraft/commands/tests/test_run.py @@ -2446,7 +2446,7 @@ class TestRun(RunBaseTestCase): @patch("lpcraft.commands.run.get_provider") @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64") - def test_run_with_additional_apt_repositories_with_secrets( + def test_provide_package_repositories_via_config_with_secrets( self, mock_get_host_architecture, mock_get_provider ): existing_repositories = [ @@ -2539,6 +2539,61 @@ class TestRun(RunBaseTestCase): file_contents, ) + @patch("lpcraft.commands.run.get_provider") + @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64") + def test_run_provide_package_repositories_via_cli( + self, mock_get_host_architecture, mock_get_provider + ): + existing_repositories = [ + "deb http://archive.ubuntu.com/ubuntu/ focal main restricted", + "deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted", + ] + + def fake_pull_file(source: Path, destination: Path) -> None: + destination.write_text("\n".join(existing_repositories)) + + launcher = Mock(spec=launch) + provider = makeLXDProvider(lxd_launcher=launcher) + mock_get_provider.return_value = provider + execute_run = launcher.return_value.execute_run + execute_run.return_value = subprocess.CompletedProcess([], 0) + launcher.return_value.pull_file.side_effect = fake_pull_file + + config = dedent( + """ + pipeline: + - test + jobs: + test: + series: focal + architectures: amd64 + run: ls -la + packages: [git] + """ # noqa: E501 + ) + Path(".launchpad.yaml").write_text(config) + + result = self.run_command("run", "--package-repository", "one more") + + self.assertEqual(0, result.exit_code) + + mock_info = launcher.return_value.push_file_io.call_args_list + self.assertEqual( + Path("/etc/apt/sources.list"), mock_info[0][1]["destination"] + ) + + file_contents = mock_info[0][1]["content"].read().decode() + self.assertEqual( + dedent( + """\ + deb http://archive.ubuntu.com/ubuntu/ focal main restricted + deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted + one more + """ # noqa: E501 + ), + file_contents, + ) + @patch("lpcraft.env.get_managed_environment_project_path") @patch("lpcraft.commands.run.get_provider") @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64") @@ -3463,7 +3518,7 @@ class TestRunOne(RunBaseTestCase): @patch("lpcraft.commands.run.get_provider") @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64") - def test_run_with_additional_apt_repositories_with_secrets( + def test_provide_package_repositories_via_config_with_secrets( self, mock_get_host_architecture, mock_get_provider ): existing_repositories = [ @@ -3558,6 +3613,63 @@ class TestRunOne(RunBaseTestCase): file_contents, ) + @patch("lpcraft.commands.run.get_provider") + @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64") + def test_run_provide_package_repositories_via_clix( + self, mock_get_host_architecture, mock_get_provider + ): + existing_repositories = [ + "deb http://archive.ubuntu.com/ubuntu/ focal main restricted", + "deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted", + ] + + def fake_pull_file(source: Path, destination: Path) -> None: + destination.write_text("\n".join(existing_repositories)) + + launcher = Mock(spec=launch) + provider = makeLXDProvider(lxd_launcher=launcher) + mock_get_provider.return_value = provider + execute_run = launcher.return_value.execute_run + execute_run.return_value = subprocess.CompletedProcess([], 0) + launcher.return_value.pull_file.side_effect = fake_pull_file + + config = dedent( + """ + pipeline: + - test + jobs: + test: + series: focal + architectures: amd64 + run: ls -la + packages: [git] + """ # noqa: E501 + ) + Path(".launchpad.yaml").write_text(config) + + result = self.run_command( + "run-one", "--package-repository", "one more", "test", "0" + ) + + self.assertEqual(0, result.exit_code) + + mock_info = launcher.return_value.push_file_io.call_args_list + self.assertEqual( + Path("/etc/apt/sources.list"), mock_info[0][1]["destination"] + ) + + file_contents = mock_info[0][1]["content"].read().decode() + self.assertEqual( + dedent( + """\ + deb http://archive.ubuntu.com/ubuntu/ focal main restricted + deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted + one more + """ # noqa: E501 + ), + file_contents, + ) + @patch("lpcraft.env.get_managed_environment_project_path") @patch("lpcraft.commands.run.get_provider") @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64") diff --git a/lpcraft/config.py b/lpcraft/config.py index e8638da..d8d2045 100644 --- a/lpcraft/config.py +++ b/lpcraft/config.py @@ -167,7 +167,7 @@ class Job(ModelConfigDefaults): input: Optional[Input] snaps: Optional[List[StrictStr]] packages: Optional[List[StrictStr]] - package_repositories: Optional[List[PackageRepository]] + package_repositories: List[PackageRepository] = [] plugin: Optional[StrictStr] plugin_config: Optional[BaseConfig]
_______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : [email protected] Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp

