Merge lp:~sergiusens/snapcraft/validation into lp:~snappy-dev/snapcraft/core

Proposed by Sergio Schvezov
Status: Merged
Approved by: Leo Arias
Approved revision: 151
Merged at revision: 141
Proposed branch: lp:~sergiusens/snapcraft/validation
Merge into: lp:~snappy-dev/snapcraft/core
Prerequisite: lp:~sergiusens/snapcraft/meta-all-yaml
Diff against target: 551 lines (+394/-9)
9 files modified
debian/control (+3/-1)
integration-tests/data/local-plugin/snapcraft.yaml (+1/-0)
schema/snapcraft.yaml (+89/-0)
setup.py (+5/-2)
snapcraft/common.py (+11/-0)
snapcraft/dirs.py (+1/-0)
snapcraft/tests/__init__.py (+1/-0)
snapcraft/tests/test_yaml.py (+251/-6)
snapcraft/yaml.py (+32/-0)
To merge this branch: bzr merge lp:~sergiusens/snapcraft/validation
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Leo Arias (community) Approve
Review via email: mp+269120@code.launchpad.net

Commit message

Initial json schema support

Description of the change

I'm just not sure where to add the tests here, so please advise during the review :-)

To post a comment you must log in.
Revision history for this message
Leo Arias (elopio) wrote :

To test, I think you should encapsulate your additions to the Config.__init__ in a validate method. Then we can pass valid and invalid yamls to it.

Some comments in the diff.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

One more comment below

Revision history for this message
Sergio Schvezov (sergiusens) :
Revision history for this message
Leo Arias (elopio) wrote :

This is great. I left some IMO comments. The only one I feel strong about is splitting the tests in scenarios or subtests.

review: Needs Fixing
Revision history for this message
Sergio Schvezov (sergiusens) wrote :

Hey you asked me for subtests a lot and I had them added explained as in the documentation you linked to ;-)

Revision history for this message
Leo Arias (elopio) wrote :

how did I not see the subtests??? Sorry about that.
So the only thing that's missing is bumping the dependency to python3 (>= 3.4),

Revision history for this message
Leo Arias (elopio) :
review: Approve
Revision history for this message
John Lenton (chipaca) wrote :

LGTM. zOMGwtfbbqschemajsonyaml, but LGTM.

review: Approve
Revision history for this message
Leo Arias (elopio) wrote :

Once this lands, the guys from erle and spreed have to be notified about the new format, right?

Revision history for this message
Snappy Tarmac (snappydevtarmac) wrote :

The attempt to merge lp:~sergiusens/snapcraft/validation into lp:snapcraft failed. Below is the output from the failed tests.

wget -c http://0.0.0.0:39937/test.tar
cp --preserve=all -R zzz /tmp/tmpo5btu74v/parts/copy/install/zzz
cp --preserve=all -R src /tmp/tmpyoazun5w/parts/copy/install/dst
cp --preserve=all -R src /tmp/tmprwukoxqe/parts/copy/install/dir/dst

...........--2015-08-27 19:50:49-- http://0.0.0.0:39937/test.tar
Connecting to 0.0.0.0:39937... connected.
HTTP request sent, awaiting response... 200 OK
Length: 22 [text/html]
Saving to: ‘test.tar’

     0K 100% 4.74M=0s

2015-08-27 19:50:49 (4.74 MB/s) - ‘test.tar’ saved [22/22]

.E.................Warning: unable to find "test_relexepath" in the path
.............E
======================================================================
ERROR: snapcraft.tests.test_cmds (unittest.loader.ModuleImportFailure)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.4/unittest/case.py", line 57, in testPartExecutor
    yield
  File "/usr/lib/python3.4/unittest/case.py", line 574, in run
    testMethod()
  File "/usr/lib/python3.4/unittest/loader.py", line 32, in testFailure
    raise exception
ImportError: Failed to import test module: snapcraft.tests.test_cmds
Traceback (most recent call last):
  File "/usr/lib/python3.4/unittest/loader.py", line 312, in _find_tests
    module = self._get_module_from_name(name)
  File "/usr/lib/python3.4/unittest/loader.py", line 290, in _get_module_from_name
    __import__(name)
  File "/tmp/tarmac/branch.04EPnA/snapcraft/tests/test_cmds.py", line 24, in <module>
    from snapcraft import (
  File "/tmp/tarmac/branch.04EPnA/snapcraft/cmds.py", line 27, in <module>
    import snapcraft.yaml
  File "/tmp/tarmac/branch.04EPnA/snapcraft/yaml.py", line 21, in <module>
    import jsonschema
ImportError: No module named 'jsonschema'

======================================================================
ERROR: snapcraft.tests.test_yaml (unittest.loader.ModuleImportFailure)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.4/unittest/case.py", line 57, in testPartExecutor
    yield
  File "/usr/lib/python3.4/unittest/case.py", line 574, in run
    testMethod()
  File "/usr/lib/python3.4/unittest/loader.py", line 32, in testFailure
    raise exception
ImportError: Failed to import test module: snapcraft.tests.test_yaml
Traceback (most recent call last):
  File "/usr/lib/python3.4/unittest/loader.py", line 312, in _find_tests
    module = self._get_module_from_name(name)
  File "/usr/lib/python3.4/unittest/loader.py", line 290, in _get_module_from_name
    __import__(name)
  File "/tmp/tarmac/branch.04EPnA/snapcraft/tests/test_yaml.py", line 17, in <module>
    import jsonschema
ImportError: No module named 'jsonschema'

----------------------------------------------------------------------
Ran 44 tests in 1.155s

FAILED (errors=2)

Revision history for this message
Sergio Schvezov (sergiusens) wrote :

On Thu, Aug 27, 2015 at 4:47 PM, Leo Arias <email address hidden> wrote:

> Once this lands, the guys from erle and spreed have to be notified about
> the new format, right?

I've disabled daily builds for now

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2015-08-07 19:49:21 +0000
+++ debian/control 2015-08-27 16:38:10 +0000
@@ -11,9 +11,10 @@
11 pep8,11 pep8,
12 plainbox,12 plainbox,
13 pyflakes,13 pyflakes,
14 python3 (>= 3.2),14 python3 (>= 3.4),
15 python3-apt,15 python3-apt,
16 python3-fixtures,16 python3-fixtures,
17 python3-jsonschema,
17 python3-setuptools,18 python3-setuptools,
18 python3-testscenarios,19 python3-testscenarios,
19 python3-yaml,20 python3-yaml,
@@ -33,6 +34,7 @@
33 dpkg-dev,34 dpkg-dev,
34 git,35 git,
35 python3-apt,36 python3-apt,
37 python3-jsonschema,
36 python3-yaml,38 python3-yaml,
37 mercurial,39 mercurial,
38 sudo,40 sudo,
3941
=== modified file 'integration-tests/data/local-plugin/snapcraft.yaml'
--- integration-tests/data/local-plugin/snapcraft.yaml 2015-08-27 16:38:09 +0000
+++ integration-tests/data/local-plugin/snapcraft.yaml 2015-08-27 16:38:10 +0000
@@ -6,3 +6,4 @@
66
7parts:7parts:
8 x-local-plugin:8 x-local-plugin:
9 source: .
910
=== added directory 'schema'
=== added file 'schema/snapcraft.yaml'
--- schema/snapcraft.yaml 1970-01-01 00:00:00 +0000
+++ schema/snapcraft.yaml 2015-08-27 16:38:10 +0000
@@ -0,0 +1,89 @@
1$schema: http://json-schema.org/draft-04/schema#
2
3title: snapcraft schema
4type: object
5properties:
6 name:
7 type: string
8 description: name of the snap package
9 pattern: "^[a-z0-9][a-z0-9+-]*$"
10 version:
11 # python's defaul yaml loading code loads 1.0 as an int
12 # type: string
13 description: package version
14 pattern: "^[a-zA-Z0-9.+~-]*$"
15 vendor:
16 type: string
17 format: email
18 summary:
19 type: string
20 description: one line summary for the package
21 maxLength: 78
22 description:
23 type: string
24 description: long description of the package
25 type:
26 type: string
27 description: the snap type, the implicit type is 'app'
28 enum:
29 - app
30 - framework
31 frameworks:
32 type: array
33 minItems: 1
34 uniqueItems: true
35 items:
36 - type: string
37 services:
38 type: array
39 items:
40 - type: object
41 properties:
42 name:
43 type: string
44 start:
45 type: string
46 description: command executed to start the service
47 stop:
48 type: string
49 description: command executed to stop the service
50 required:
51 - name
52 - start
53 binaries:
54 type: array
55 items:
56 - type: object
57 properties:
58 name:
59 type: string
60 exec:
61 type: string
62 description: command executed to start the service
63 required:
64 - name
65 parts:
66 type: object
67 minProperties: 1
68 patternProperties:
69 ^[a-z0-9][a-z0-9+-]*$:
70 type: object
71 properties:
72 plugin:
73 type: string
74 description: plugin name
75 source:
76 type: string
77 description: path to the sources
78 # TODO To be enabled once the Ubuntu plugin is removed
79 # required:
80 # - plugin
81 # - source
82 addtionalProperties: false
83required:
84 - name
85 - version
86 - vendor
87 - summary
88 - description
89 - parts
090
=== modified file 'setup.py'
--- setup.py 2015-07-06 16:48:22 +0000
+++ setup.py 2015-08-27 16:38:10 +0000
@@ -36,6 +36,9 @@
36 'snapcraft.plugins'],36 'snapcraft.plugins'],
37 package_data={'snapcraft.plugins': ['manifest.txt']},37 package_data={'snapcraft.plugins': ['manifest.txt']},
38 scripts=['bin/snapcraft'],38 scripts=['bin/snapcraft'],
39 data_files=[('share/snapcraft/plugins', ['plugins/' + x for x in os.listdir('plugins')])],39 data_files=[
40 ('share/snapcraft/plugins', ['plugins/' + x for x in os.listdir('plugins')]),
41 ('share/snapcraft/schema', ['schema/' + x for x in os.listdir('schema')]),
42 ],
40 cmdclass={'test': TestCommand},43 cmdclass={'test': TestCommand},
41)44 )
4245
=== modified file 'snapcraft/common.py'
--- snapcraft/common.py 2015-08-05 15:39:18 +0000
+++ snapcraft/common.py 2015-08-27 16:38:10 +0000
@@ -25,6 +25,8 @@
25COMMAND_ORDER = ["pull", "build", "stage", "snap"]25COMMAND_ORDER = ["pull", "build", "stage", "snap"]
26_DEFAULT_PLUGINDIR = '/usr/share/snapcraft/plugins'26_DEFAULT_PLUGINDIR = '/usr/share/snapcraft/plugins'
27_plugindir = _DEFAULT_PLUGINDIR27_plugindir = _DEFAULT_PLUGINDIR
28_DEFAULT_SCHEMADIR = '/usr/share/snapcraft/schema'
29_schemadir = _DEFAULT_SCHEMADIR
28_arch = None30_arch = None
29_arch_triplet = None31_arch_triplet = None
3032
@@ -79,3 +81,12 @@
7981
80def get_plugindir():82def get_plugindir():
81 return _plugindir83 return _plugindir
84
85
86def set_schemadir(schemadir):
87 global _schemadir
88 _schemadir = schemadir
89
90
91def get_schemadir():
92 return _schemadir
8293
=== modified file 'snapcraft/dirs.py'
--- snapcraft/dirs.py 2015-07-23 17:19:25 +0000
+++ snapcraft/dirs.py 2015-08-27 16:38:10 +0000
@@ -27,3 +27,4 @@
27 # only change the default if we are running from a checkout27 # only change the default if we are running from a checkout
28 if os.path.exists(os.path.join(topdir, "setup.py")):28 if os.path.exists(os.path.join(topdir, "setup.py")):
29 common.set_plugindir(os.path.join(topdir, 'plugins'))29 common.set_plugindir(os.path.join(topdir, 'plugins'))
30 common.set_schemadir(os.path.join(topdir, 'schema'))
3031
=== modified file 'snapcraft/tests/__init__.py'
--- snapcraft/tests/__init__.py 2015-08-04 15:06:59 +0000
+++ snapcraft/tests/__init__.py 2015-08-27 16:38:10 +0000
@@ -32,3 +32,4 @@
32 # is a module variable. Make sure that it is returned to the original32 # is a module variable. Make sure that it is returned to the original
33 # value when a test ends.33 # value when a test ends.
34 self.addCleanup(common.set_plugindir, common.get_plugindir())34 self.addCleanup(common.set_plugindir, common.get_plugindir())
35 self.addCleanup(common.set_schemadir, common.get_schemadir())
3536
=== modified file 'snapcraft/tests/test_yaml.py'
--- snapcraft/tests/test_yaml.py 2015-08-05 18:40:06 +0000
+++ snapcraft/tests/test_yaml.py 2015-08-27 16:38:10 +0000
@@ -14,15 +14,18 @@
14# You should have received a copy of the GNU General Public License14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.15# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
17import jsonschema
17import logging18import logging
18import os19import os
19import tempfile20import tempfile
20import unittest21import unittest
22import unittest.mock
2123
22import fixtures24import fixtures
2325
26import snapcraft.common
27import snapcraft.yaml
24from snapcraft import dirs28from snapcraft import dirs
25from snapcraft.yaml import Config
26from snapcraft.tests import TestCase29from snapcraft.tests import TestCase
2730
2831
@@ -37,11 +40,19 @@
3740
38 @unittest.mock.patch('snapcraft.yaml.Config.load_plugin')41 @unittest.mock.patch('snapcraft.yaml.Config.load_plugin')
39 def test_config_loads_plugins(self, mock_loadPlugin):42 def test_config_loads_plugins(self, mock_loadPlugin):
40 self.make_snapcraft_yaml("""parts:43 dirs.setup_dirs()
44
45 self.make_snapcraft_yaml("""name: test
46version: "1"
47vendor: me <me@me.com>
48summary: test
49description: test
50
51parts:
41 ubuntu:52 ubuntu:
42 packages: [fswebcam]53 packages: [fswebcam]
43""")54""")
44 Config()55 snapcraft.yaml.Config()
45 mock_loadPlugin.assert_called_with("ubuntu", "ubuntu", {56 mock_loadPlugin.assert_called_with("ubuntu", "ubuntu", {
46 "packages": ["fswebcam"],57 "packages": ["fswebcam"],
47 })58 })
@@ -52,7 +63,7 @@
5263
53 # no snapcraft.yaml64 # no snapcraft.yaml
54 with self.assertRaises(SystemExit) as raised:65 with self.assertRaises(SystemExit) as raised:
55 Config()66 snapcraft.yaml.Config()
5667
57 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')68 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')
58 self.assertEqual(69 self.assertEqual(
@@ -66,7 +77,13 @@
66 fake_logger = fixtures.FakeLogger(level=logging.ERROR)77 fake_logger = fixtures.FakeLogger(level=logging.ERROR)
67 self.useFixture(fake_logger)78 self.useFixture(fake_logger)
6879
69 self.make_snapcraft_yaml("""parts:80 self.make_snapcraft_yaml("""name: test
81version: "1"
82vendor: me <me@me.com>
83summary: test
84description: test
85
86parts:
70 p1:87 p1:
71 plugin: ubuntu88 plugin: ubuntu
72 after: [p2]89 after: [p2]
@@ -75,7 +92,235 @@
75 after: [p1]92 after: [p1]
76""")93""")
77 with self.assertRaises(SystemExit) as raised:94 with self.assertRaises(SystemExit) as raised:
78 Config()95 snapcraft.yaml.Config()
7996
80 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')97 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')
81 self.assertEqual('Circular dependency chain!\n', fake_logger.output)98 self.assertEqual('Circular dependency chain!\n', fake_logger.output)
99
100 @unittest.mock.patch('snapcraft.yaml.Config.load_plugin')
101 def test_invalid_yaml_missing_name(self, mock_loadPlugin):
102 dirs.setup_dirs()
103
104 fake_logger = fixtures.FakeLogger(level=logging.ERROR)
105 self.useFixture(fake_logger)
106
107 self.make_snapcraft_yaml("""
108version: "1"
109vendor: me <me@me.com>
110summary: test
111description: nothing
112
113parts:
114 ubuntu:
115 packages: [fswebcam]
116""")
117 with self.assertRaises(SystemExit) as raised:
118 snapcraft.yaml.Config()
119
120 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')
121 self.assertEqual(
122 'Issues while validating snapcraft.yaml: \'name\' is a required property\n',
123 fake_logger.output)
124
125 @unittest.mock.patch('snapcraft.yaml.Config.load_plugin')
126 def test_invalid_yaml_invalid_name_as_number(self, mock_loadPlugin):
127 dirs.setup_dirs()
128
129 fake_logger = fixtures.FakeLogger(level=logging.ERROR)
130 self.useFixture(fake_logger)
131
132 self.make_snapcraft_yaml("""name: 1
133version: "1"
134vendor: me <me@me.com>
135summary: test
136description: nothing
137
138parts:
139 ubuntu:
140 packages: [fswebcam]
141""")
142 with self.assertRaises(SystemExit) as raised:
143 snapcraft.yaml.Config()
144
145 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')
146 self.assertEqual(
147 'Issues while validating snapcraft.yaml: 1 is not of type \'string\'\n',
148 fake_logger.output)
149
150 @unittest.mock.patch('snapcraft.yaml.Config.load_plugin')
151 def test_invalid_yaml_invalid_name_chars(self, mock_loadPlugin):
152 dirs.setup_dirs()
153
154 fake_logger = fixtures.FakeLogger(level=logging.ERROR)
155 self.useFixture(fake_logger)
156
157 self.make_snapcraft_yaml("""name: myapp@me_1.0
158version: "1"
159vendor: me <me@me.com>
160summary: test
161description: nothing
162
163parts:
164 ubuntu:
165 packages: [fswebcam]
166""")
167 with self.assertRaises(SystemExit) as raised:
168 snapcraft.yaml.Config()
169
170 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')
171 self.assertEqual(
172 'Issues while validating snapcraft.yaml: \'myapp@me_1.0\' does not match \'^[a-z0-9][a-z0-9+-]*$\'\n',
173 fake_logger.output)
174
175 @unittest.mock.patch('snapcraft.yaml.Config.load_plugin')
176 def test_invalid_yaml_missing_description(self, mock_loadPlugin):
177 dirs.setup_dirs()
178
179 fake_logger = fixtures.FakeLogger(level=logging.ERROR)
180 self.useFixture(fake_logger)
181
182 self.make_snapcraft_yaml("""name: test
183version: "1"
184vendor: me <me@me.com>
185summary: test
186
187parts:
188 ubuntu:
189 packages: [fswebcam]
190""")
191 with self.assertRaises(SystemExit) as raised:
192 snapcraft.yaml.Config()
193
194 self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.')
195 self.assertEqual(
196 'Issues while validating snapcraft.yaml: \'description\' is a required property\n',
197 fake_logger.output)
198
199
200class TestValidation(TestCase):
201
202 def setUp(self):
203 super().setUp()
204 dirs.setup_dirs()
205
206 self.data = {
207 'name': 'my-package-1',
208 'version': '1.0-snapcraft1~ppa1',
209 'vendor': 'Me <me@me.com>',
210 'summary': 'my summary less that 79 chars',
211 'description': 'description which can be pretty long',
212 'parts': {
213 'part1': {
214 'type': 'project',
215 },
216 },
217 }
218
219 def test_required_properties(self):
220 for key in self.data:
221 data = self.data.copy()
222 with self.subTest(key=key):
223 del data[key]
224
225 with self.assertRaises(jsonschema.ValidationError) as raised:
226 snapcraft.yaml._validate_snapcraft_yaml(data)
227
228 expected_message = '\'{}\' is a required property'.format(key)
229 self.assertEqual(raised.exception.message, expected_message, msg=data)
230
231 def test_invalid_names(self):
232 invalid_names = [
233 'package@awesome',
234 'something.another',
235 '_hideme',
236 ]
237
238 for name in invalid_names:
239 data = self.data.copy()
240 with self.subTest(key=name):
241 data['name'] = name
242
243 with self.assertRaises(jsonschema.ValidationError) as raised:
244 snapcraft.yaml._validate_snapcraft_yaml(data)
245
246 expected_message = '\'{}\' does not match \'^[a-z0-9][a-z0-9+-]*$\''.format(name)
247 self.assertEqual(raised.exception.message, expected_message, msg=data)
248
249 def test_summary_too_long(self):
250 self.data['summary'] = 'a' * 80
251 with self.assertRaises(jsonschema.ValidationError) as raised:
252 snapcraft.yaml._validate_snapcraft_yaml(self.data)
253
254 expected_message = '\'{}\' is too long'.format(self.data['summary'])
255 self.assertEqual(raised.exception.message, expected_message, msg=self.data)
256
257 def test_valid_types(self):
258 self.data['type'] = 'app'
259 snapcraft.yaml._validate_snapcraft_yaml(self.data)
260
261 self.data['type'] = 'framework'
262 snapcraft.yaml._validate_snapcraft_yaml(self.data)
263
264 def test_invalid_types(self):
265 invalid_types = [
266 'apps',
267 'kernel',
268 'platform',
269 'oem',
270 'os',
271 ]
272
273 for t in invalid_types:
274 data = self.data.copy()
275 with self.subTest(key=t):
276 data['type'] = t
277
278 with self.assertRaises(jsonschema.ValidationError) as raised:
279 snapcraft.yaml._validate_snapcraft_yaml(data)
280
281 expected_message = '\'{}\' is not one of [\'app\', \'framework\']'.format(t)
282 self.assertEqual(raised.exception.message, expected_message, msg=data)
283
284 def test_valid_services(self):
285 self.data['services'] = [
286 {
287 'name': 'service1',
288 'start': 'binary1 start',
289 },
290 {
291 'name': 'service2',
292 'start': 'binary2',
293 'stop': 'binary2 --stop',
294 },
295 {
296 'name': 'service3',
297 }
298 ]
299
300 snapcraft.yaml._validate_snapcraft_yaml(self.data)
301
302 def test_services_required_properties(self):
303 self.data['services'] = [
304 {
305 'start': 'binary1 start',
306 }
307 ]
308
309 with self.assertRaises(jsonschema.ValidationError) as raised:
310 snapcraft.yaml._validate_snapcraft_yaml(self.data)
311
312 expected_message = '\'name\' is a required property'
313 self.assertEqual(raised.exception.message, expected_message, msg=self.data)
314
315 def test_schema_file_not_found(self):
316 mock_the_open = unittest.mock.mock_open()
317 mock_the_open.side_effect = FileNotFoundError()
318
319 with unittest.mock.patch('snapcraft.yaml.open', mock_the_open, create=True):
320 with self.assertRaises(snapcraft.yaml.SchemaNotFoundError) as raised:
321 snapcraft.yaml._validate_snapcraft_yaml(self.data)
322
323 expected_path = os.path.join(snapcraft.common.get_schemadir(), 'snapcraft.yaml')
324 mock_the_open.assert_called_once_with(expected_path)
325 expected_message = 'Schema is missing, could not validate snapcraft.yaml, check installation'
326 self.assertEqual(raised.exception.message, expected_message)
82327
=== modified file 'snapcraft/yaml.py'
--- snapcraft/yaml.py 2015-08-26 08:52:09 +0000
+++ snapcraft/yaml.py 2015-08-27 16:38:10 +0000
@@ -18,6 +18,8 @@
18import sys18import sys
1919
20import yaml20import yaml
21import jsonschema
22import os
2123
22import snapcraft.plugin24import snapcraft.plugin
23from snapcraft import common25from snapcraft import common
@@ -26,6 +28,24 @@
26logger = logging.getLogger(__name__)28logger = logging.getLogger(__name__)
2729
2830
31class SchemaNotFoundError(Exception):
32
33 def __init__(self, message):
34 self.message = message
35
36
37def _validate_snapcraft_yaml(snapcraft_yaml):
38 schema_file = os.path.abspath(os.path.join(common.get_schemadir(), 'snapcraft.yaml'))
39
40 try:
41 with open(schema_file) as fp:
42 schema = yaml.load(fp)
43 except FileNotFoundError:
44 raise SchemaNotFoundError('Schema is missing, could not validate snapcraft.yaml, check installation')
45
46 jsonschema.validate(snapcraft_yaml, schema)
47
48
29class Config:49class Config:
3050
31 def __init__(self):51 def __init__(self):
@@ -39,6 +59,18 @@
39 except FileNotFoundError:59 except FileNotFoundError:
40 logger.error("Could not find snapcraft.yaml. Are you sure you're in the right directory?\nTo start a new project, use 'snapcraft init'")60 logger.error("Could not find snapcraft.yaml. Are you sure you're in the right directory?\nTo start a new project, use 'snapcraft init'")
41 sys.exit(1)61 sys.exit(1)
62
63 # Make sure the loaded snapcraft yaml follows the schema
64 try:
65 _validate_snapcraft_yaml(self.data)
66 except SchemaNotFoundError as e:
67 logger.error(e.message)
68 sys.exit(1)
69 except jsonschema.ValidationError as e:
70 msg = "Issues while validating snapcraft.yaml: {}".format(e.message)
71 logger.error(msg)
72 sys.exit(1)
73
42 self.build_tools = self.data.get('build-tools', [])74 self.build_tools = self.data.get('build-tools', [])
4375
44 for part_name in self.data.get("parts", []):76 for part_name in self.data.get("parts", []):

Subscribers

People subscribed via source and target branches