launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #28983
[Merge] ~jugmac00/lpcraft:provide-additional-repositories-via-cli into lpcraft:main
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]
Follow ups