-
Notifications
You must be signed in to change notification settings - Fork 440
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
project: introduce build-snaps #1518
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am eager to see this released.
I left a few comments. And this is missing the recording part. Do you plan to do it as part of this branch, or leave it for (me, probably) later?
@@ -276,6 +276,9 @@ properties: | |||
stage-packages: | |||
$ref: "#/definitions/grammar-array" | |||
default: [] # For some reason this doesn't work if in the ref | |||
build-snaps: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
¡viva! this is the end of compiling go1.8 on every build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
go 1.9 now, already...
@@ -276,6 +276,9 @@ properties: | |||
stage-packages: | |||
$ref: "#/definitions/grammar-array" | |||
default: [] # For some reason this doesn't work if in the ref | |||
build-snaps: | |||
$ref: "#/definitions/grammar-array" | |||
default: [] # For some reason this doesn't work if in the ref |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hum, I haven't seen this before. It's ok to leave a comment, but it needs more information.
What doesn't work, specifically? I guess this is a question for @kyrofa.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I initially wrote the grammar back in the day I wasn't sure what was happening, and decided it was a jsonschema quirk. However, now that you ask I looked into it with a fresh mind and I think I know what's actually happening: a jsonschema ref isn't expanded in any fancy way by the YAML (which is why I'd like to use a recursive YAML anchor for this, but jsonschema causes things to explode that way since it wants to walk the whole thing). This means that we can't actually access the chunk of YAML representing that bit of the schema very easily in code. Like we do here to expand defaults. So this is kind of an ugly hack to allow specifying the defaults to continue actually resulting in defaults. Thankfully that's the only field for which I imagine we'll need this hack.
@@ -89,6 +89,7 @@ def __init__(self, project_options=None): | |||
if project_options is None: | |||
project_options = snapcraft.ProjectOptions() | |||
|
|||
self.build_snaps = set() | |||
self.build_tools = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have I said how much I hate this build_tools? :D
I'm just saying it again to put myself pressure to fix it.
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing empty line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this I will indeed ignore ;-)
snapcraft/internal/repo/snaps.py
Outdated
|
||
@classmethod | ||
def is_valid_snap(cls, snap): | ||
return cls(snap).is_valid() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I consider this very weird. A class method that makes an instance. I haven't seen it before, is it an accepted pattern?
I would prefer the caller to make the instance. Or, a little less preferable, to make is_valid_snap a module function instead of a class method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a common pattern, yes
snapcraft/internal/repo/snaps.py
Outdated
self.get_store_snap_info() | ||
return self._is_on_store | ||
|
||
def get_local_snap_info(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for not putting an _ in front of this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no reason for the fact that it can be used outside even though it isn't right now.
snapcraft/internal/repo/snaps.py
Outdated
@property | ||
def on_store(self): | ||
if self._is_on_store is None: | ||
self.get_store_snap_info() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment about assigning _is_on_store
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means I also need ancillary values for the actual info which I was trying to avoid.
snapcraft/internal/repo/snaps.py
Outdated
if not self.on_store: | ||
return dict() | ||
|
||
return snap_store_info['result'][0]['channels'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that 0
because multiple results can be returned? It would be nice to explain that in a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I had it in a comment somewhere else before moving this to a class.
snapcraft/internal/repo/snaps.py
Outdated
if self._original_channel: | ||
snap_install_cmd.extend(['--channel', self._original_channel]) | ||
if self.is_classic: | ||
snap_install_cmd.extend(['--classic']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I now this would complicate the snapcraft.yaml, but I would prefer the user to declare if she wants to install the snap as classic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not what was agreed to on the forum 😉
snapcraft/internal/repo/snaps.py
Outdated
try: | ||
check_call(snap_refresh_cmd) | ||
except CalledProcessError as install_error: | ||
raise errors.SnapInstallError(snap_name=self.name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A Refresh error would be more appropriate here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it
2444f3c
to
c26600a
Compare
def __init__(self, parts, project_options, validator, build_tools, | ||
snapcraft_yaml): | ||
def __init__(self, parts, project_options, validator, | ||
build_snaps, build_tools, snapcraft_yaml): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a * here and use keywords?
snapcraft/internal/repo/snaps.py
Outdated
if not snap_pkg.installed and snap_pkg.on_store: | ||
snap_pkg.install() | ||
elif snap_pkg.get_current_channel() != snap_pkg.channel: | ||
snap_pkg.refresh() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also check if is_classic is the same and requires a refresh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, right, for people who bounce back and forth; in general terms if installed once with classic you don't need to pass it on for subsequent installs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, I'm talking about the case where snap foo has strict confinement and a new revision is a classic snap, or vice versa. Afair snapd doesn't change it automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, that is what I meant by bounce back and forth 😉
self.fail( | ||
'This integration test cannot run if you already have the ' | ||
"'hello' package installed. Please uninstall it before " | ||
'running this test.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should say "if you already have the 'hello' snap installed", otherwise it makes you think of apt or dnf. Also, print the command that does that.
snap_channel=self.channel) | ||
|
||
def refresh(self): | ||
"""Refreshes a snap onto a channel on the system.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be Refreshes a snap to the latest version, channel and confinement type
because 1) it will update the snap if there's a new version 2) as per my comment on install_snaps
confinement may have changed.
snap_pkg.refresh() | ||
|
||
|
||
def _snap_command_requires_sudo(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a unit test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, unittest for this whole module coming today :-)
snapcraft/internal/repo/snaps.py
Outdated
snap_install_cmd.extend(['snap', 'install', self.name]) | ||
if self._original_channel: | ||
snap_install_cmd.extend(['--channel', self._original_channel]) | ||
if self.is_classic: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is missing the TODO comment to make it a user choice on non ci/container environments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is done in the is_classic
check now
snapcraft/internal/repo/snaps.py
Outdated
confinment value and channel availability. | ||
|
||
This information can also be used determine if a snap should be | ||
installed or refreshed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a "to" in here: "This information can also be used to determine[...]"
snapcraft/internal/repo/snaps.py
Outdated
return self._is_installed | ||
|
||
@property | ||
def on_store(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the store, or in the store?
snap_install_cmd = [] | ||
if _snap_command_requires_sudo(): | ||
snap_install_cmd = ['sudo'] | ||
snap_install_cmd.extend(['snap', 'install', self.name]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an advantage to shelling out as opposed to using the snapd API for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is much more work as we'd need to take care of "uploading" the snap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait, not for these snaps. Maybe not, let me look
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave this for future work, I don't even know how stable that API is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nor where it is documented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, fair enough.
store_channels = self._get_store_channels() | ||
return self.channel in store_channels.keys() | ||
|
||
def install(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the snap I want to use to build requires devmode? Are we choosing to not support that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not at the moment, check the forum post on the subject
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did. It says nothing about devmode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, so it would need a discussion first, right now it shouldn't work. In all fairness, if we discuss this, I'd say it shouldn't just like we are not auto connecting interfaces.
snapcraft/internal/repo/snaps.py
Outdated
def _get_parsed_snap(snap): | ||
if '/' in snap: | ||
snap_name = snap[:snap.find('/')] | ||
snap_channel = snap[snap.find('/')+1:] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two snap.find('/')
s here are bothering me-- perhaps it should be saved in a variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, fair enough
tools/travis/run_lxd_container.sh
Outdated
@@ -32,7 +32,7 @@ name="$1" | |||
lxc="/snap/bin/lxc" | |||
|
|||
echo "Starting the LXD container." | |||
$lxc launch --ephemeral ubuntu:xenial "$name" | |||
$lxc launch --ephemeral --config security.privileged=true ubuntu:xenial "$name" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need privileged containers here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commit that added this has the info, but here it is: https://bugs.launchpad.net/snapd/+bug/1709536
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, I hit that myself. I fixed it by removing the Nice value from the systemd unit file though as opposed to making the container privileged. It's probably not a big deal, let's just keep an eye on the bug and change back to unprivileged once it's fixed. Can we add a FIXME comment or something, though, with a link to the bug?
b160719
to
a427c09
Compare
snapcraft/internal/repo/snaps.py
Outdated
snap_install_cmd.extend(['--channel', self._original_channel]) | ||
if self.is_classic: | ||
# TODO make this a user explicit choice | ||
snap_install_cmd.extend(['--classic']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should just be .append()
no need to .extend()
with a single item list
snapcraft/internal/repo/snaps.py
Outdated
'--channel', self.channel]) | ||
if self.is_classic: | ||
# TODO make this a user explicit choice | ||
snap_refresh_cmd.extend(['--classic']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More .extend()
waste
snapcraft/internal/repo/snaps.py
Outdated
def _get_store_snap_info(snap_name): | ||
# This logic uses /v2/find returns an array of results, given that | ||
# we do a strict search either 1 result or a 404 will be returned. | ||
slug = '{}{}'.format('find?name=', urllib.parse.quote(snap_name, safe='')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huh? why are you interpolating a fixed string?
'find?name={}'.format(...)` would be more intuitive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason for not using urllib.parse.urlencode
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW using urllib.parse.quote
like that results in unnecessary %-encoding of characters that don't need it. If you'd rather not use urlencode
(maybe building a dict isn't to your taste?), just use urllib.parse.quote_plus
which is the quote function for the query part of a URL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requests_unixsockets
doesn't support the dict as params, but I guess you are implying that urlencode can do that so i'll take a look. The only one I sort of have problems with is urljoin
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switched to urlencode
on bec56ed
snapcraft/internal/repo/snaps.py
Outdated
if current_channel == 'stable': | ||
current_channel = 'latest/stable' | ||
if current_channel in ('stable', 'candidate', 'beta', 'edge'): | ||
current_channel = 'latest/{}'.format(current_channel) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check won't catch branches, think build-snaps: go/hotfix-211
. Perhaps instead of a whitelist of risks, just check to see if a track is specified (e.g. searching for /
)?
snapcraft/tests/repo/test_snaps.py
Outdated
return 'email: -'.encode() | ||
|
||
|
||
class FakeSnapdServer(BaseHTTPRequestHandler): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having @chipaca look this fake over to make sure everything is sane would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sort of asked him the necessary questions about API and showed him the original implementation so I don't think he is needed her @kyrofa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can confirm, was sort of asked.
abadb8c
to
91737a3
Compare
return (request, client_address) | ||
|
||
|
||
class FakeSnapd(fixtures.Fixture): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like your new FakeSnapd a lot. But we already have a FakeSnapd fixture in snapcraft/tests/fixture_setup.py
so please merge the two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather not do it here as it would require substantial changes. I'll do it in a follow up PR though.
snapcraft/tests/repo/test_snaps.py
Outdated
self.fake_snap_command.refresh_success = False | ||
self.assertRaises(errors.SnapRefreshError, snap_pkg.refresh) | ||
|
||
def test_bundle_install(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the term "bundle" confused me. I think test_install_multiple
would be much clearer.
snapcraft/tests/repo/test_snaps.py
Outdated
self.assertThat(snap_pkg.in_store, Is(self.expected)) | ||
|
||
|
||
class SnapPackageIsClasicTest(SnapPackageBaseTestCase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: SnapPackageIsClassicTest should have two s.
snap_pkg = snaps.SnapPackage('fake-snap/classic/stable') | ||
snap_pkg.install() | ||
self.assertThat(self.fake_snap_command.calls, Equals([ | ||
['snap', 'whoami'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a test missing for the case of a logged in user where sudo
won't be used.
bec56ed
to
45bebb6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good to me.
I tested it with a few real snaps. Now we need for the go plugin to not install golang-go from the archive.
I'm a couple of integration tests that install a snap with track and risk.
class BuildSnapGrammarTestCase(testscenarios.WithScenarios, | ||
integration_tests.TestCase): | ||
|
||
scenarios = _construct_scenarios() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I would use multiply here, but if this makes you happy, ok :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I saw multiply, this feels much more readable IMO, the other options was as @sparkiegeek mentioned, subTest
but iirc, testscenarios
had issues with that, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right: testing-cabal/testtools#235
snapcraft/internal/repo/snaps.py
Outdated
|
||
It uses information provided by snapd implicitly referring to the local | ||
and remote stores to obtain information about the snap, such as its | ||
confinment value and channel availability. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: confinement.
except subprocess.CalledProcessError as e: | ||
self.fail("unable to remove 'hello': {}".format(e.output)) | ||
|
||
def _hello_is_installed(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_is_hello_installed
should be the name of this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replicated what was in test_build_package_grammar
. Let's change this in a different PR.
self.calls.append(cmd) | ||
return self._fake_snap_command(cmd, *args, **kwargs) | ||
else: | ||
return original(cmd, *args, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, I like this! ;)
elif cmd == 'refresh' and not self.refresh_success: | ||
raise subprocess.CalledProcessError(returncode=1, cmd=cmd) | ||
elif cmd == 'whoami': | ||
return 'email: {}'.format(self._email).encode() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been reflecting upon these fakes. I think things would be a lot easier if we always called check_output, even when we don't care about the output. That way we only have to make one patch. And if there is only one patch, and in good theory the test should only call the patched function once, then the test itself could inject the exception to raise. That would be clearer to me. But well, all random thoughts for future improvement, we can discuss about the fake tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using check_output
only will not stream the output to stdout
which is a feature. If you must, we should migrate to our own runner based on Popen
snapcraft/tests/repo/test_snaps.py
Outdated
return 'email: {}'.format(self._email).encode() | ||
|
||
|
||
class FakeSnapdServer(BaseHTTPRequestHandler): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this fake to snapcraft/tests/fake_servers/snapd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My next step after this PR is to refactor fixtures_setup
and others to make it more readable, I was lost inside those modules while trying to make out some structure from it
snapcraft/tests/repo/test_snaps.py
Outdated
params = {'channel': 'track/stable/branch'} | ||
elif parsed_url.path.endswith('/fake-snap-edge'): | ||
status_code = 200 | ||
params = {'channel': 'edge'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unending stream of elifs caused many problems when we left the fake servers evolve. That's why on the new ones we are using pyramid to route the requests. This is not a lot better, just a little, but it will help for when we are finally able to use https://github.com/pretenders/pretenders
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like complicating things at the start though.
@@ -25,9 +25,12 @@ lxc="/snap/bin/lxc" | |||
|
|||
"$script_path/setup_lxd.sh" | |||
"$script_path/run_lxd_container.sh" snap-builder | |||
# Workaround for | |||
# - Setup snap "core" (2462) security profiles (cannot reload udev rules: exit status 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a bug for this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no idea, I was told it was known
snapcraft/tests/repo/test_snaps.py
Outdated
dict(snap='fake-snap-branch/candidate/branch', | ||
expected='latest/candidate/branch')), | ||
('track/stable/branch', | ||
dict(snap='fake-snap-track-stable-branch/trakc/stable/branch', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a typo here: trakc/track.
This is one of the good reasons to migrate out of those hard-coded fake servers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, but in the case of this test fixture the request for the future is never made, if I had called it, I would of gotten an error (like install
or is_classic
)
Introduce build-snaps with support for advanced grammar. Fixes canonical#1442
This is a workaround for LP: #1709536
abb8763
to
a211b19
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 from the phone, like kids do \•/
Introduce build-snaps with support for advanced grammar. Fixes canonical#1442
Introduce build-snaps with support for advanced grammar.