Home | History | Annotate | Download | only in recipes
      1 # Copyright 2017 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 # Recipe which:
      6 # 1) Extracts all fiddles out of markdown files.
      7 # 2) Forces fiddle.skia.org to compile all those fiddles and get output in JSON.
      8 # 3) Scans the output and reports any compiletime/runtime errors.
      9 # 4) Updates markdown in site/user/api/ using the new hashes (if any) from
     10 #    fiddle.skia.org.
     11 
     12 import json
     13 
     14 
     15 DEPS = [
     16   'recipe_engine/context',
     17   'recipe_engine/file',
     18   'recipe_engine/path',
     19   'recipe_engine/properties',
     20   'recipe_engine/step',
     21   'core',
     22   'infra',
     23   'run',
     24   'vars',
     25 ]
     26 
     27 UPDATE_DOCS_GITCOOKIES_FILE = 'update_docs.git_cookies'
     28 UPDATE_DOCS_GITCOOKIES_GS_PATH = (
     29     'gs://skia-buildbots/artifacts/server/.gitcookies_update-docs')
     30 
     31 
     32 def go_get_fiddlecli(api):
     33   env = api.context.env
     34   env.update(api.infra.go_env)
     35   with api.context(env=env):
     36     api.run.with_retry(
     37         api.step,
     38         'go get fiddlecli',
     39         5,  # Update attempts.
     40         cmd=[api.infra.go_exe, 'get', '-u', '-t',
     41              'go.skia.org/infra/fiddle/go/fiddlecli'])
     42 
     43 
     44 def RunSteps(api):
     45   api.vars.setup()
     46   api.core.checkout_bot_update()
     47   api.infra.go_version()
     48   go_get_fiddlecli(api)
     49 
     50   with api.context(cwd=api.vars.skia_dir, env=api.infra.go_env):
     51     bookmaker_binary = api.path.join(api.vars.skia_out, api.vars.configuration,
     52                                      'bookmaker')
     53     buildername = api.vars.builder_name
     54 
     55     if 'PerCommit' in buildername:
     56       # Check to see if docs matches include/core.
     57       cmd = [bookmaker_binary,
     58              '-a', 'docs/status.json',  # File containing status of docs.
     59              '-x',  # Check bmh against includes.
     60              ]
     61       try:
     62         api.run(api.step, 'Validate docs match include/core/*.h', cmd=cmd)
     63       except api.step.StepFailure as e:
     64         # Display what needs to be fixed.
     65         e.reason += (
     66             '\n\nView the output of the "Validate docs match include/core/*.h" '
     67             'step to see how to get this bot green.'
     68             '\n\nhttps://skia.org/user/api/usingBookmaker details how to build '
     69             'and run the bookmaker utility locally if needed.')
     70         raise e
     71 
     72     elif 'Nightly' in buildername:
     73       fiddlecli_binary = api.path.join(api.infra.gopath, 'bin', 'fiddlecli')
     74       fiddlecli_input = api.path.join(api.path['start_dir'], 'fiddle.json')
     75       fiddlecli_output = api.path.join(api.path['start_dir'], 'fiddleout.json')
     76 
     77       # Step 1: Extract all fiddles out of markdown files.
     78       cmd = [bookmaker_binary,
     79              '-a', 'docs/status.json',  # File containing status of docs.
     80              '-e', fiddlecli_input,  # Fiddle cli input.
     81              ]
     82       api.run(api.step, 'Extract all fiddles out of md files', cmd=cmd)
     83 
     84       # Step 2: Forces fiddle.skia.org to compile all fiddles extracted out of
     85       #         markdown files and get output in JSON.
     86       cmd = [fiddlecli_binary,
     87              '--input', fiddlecli_input,
     88              '--output', fiddlecli_output,
     89              '--logtostderr',
     90              '--force',
     91           ]
     92       api.run(api.step, 'Force fiddle to compile all examples', cmd=cmd)
     93 
     94       # Step 3: Scan the output of fiddlecli for any compiletime/runtime errors.
     95       #         Fail the recipe is there are any errors and summarize results at
     96       #         the end.
     97       if api.path.exists(fiddlecli_output):
     98         test_data = api.properties.get('fiddleout_test_data', '{}')
     99         content = api.file.read_text('Read fiddleout.json',
    100                                      fiddlecli_output, test_data=test_data)
    101         out = json.loads(content)
    102         # Do a dump of fiddlecli_output. Will be useful for debugging.
    103         print 'Dump of %s:' % fiddlecli_output
    104         print json.dumps(out, indent=4)
    105 
    106         failing_fiddles_to_errors = {}
    107         for fiddle_name in out:
    108           props = out[fiddle_name]
    109           if props['compile_errors'] or props['runtime_error']:
    110             # Construct the error.
    111             error = props['runtime_error']
    112             if props['compile_errors']:
    113               for e in props['compile_errors']:
    114                 error += '%s\n' % e['text']
    115             failing_fiddles_to_errors[props['fiddleHash']] = error
    116 
    117         if failing_fiddles_to_errors:
    118           # create an eror message and fail the bot!
    119           failure_msg = 'Failed fiddles with their errors:\n\n\n'
    120           counter = 0
    121           for fiddle_hash, error in failing_fiddles_to_errors.iteritems():
    122             counter += 1
    123             failure_msg += '%d. https://fiddle.skia.org/c/%s\n\n' % (
    124                 counter, fiddle_hash)
    125             failure_msg += '%s\n\n' % error
    126           raise api.step.StepFailure(failure_msg)
    127 
    128       # Step 4: Update docs in site/user/api/ with the output of fiddlecli.
    129       #         If there are any new changes then upload and commit the changes.
    130       update_docs_gitcookies = api.path['start_dir'].join(
    131           UPDATE_DOCS_GITCOOKIES_FILE)
    132       cmd = ['python',
    133              api.vars.skia_dir.join('infra', 'bots', 'upload_md.py'),
    134             '--bookmaker_binary', bookmaker_binary,
    135              '--fiddlecli_output', fiddlecli_output,
    136             '--gitcookies', str(update_docs_gitcookies)]
    137       with api.infra.DownloadGitCookies(
    138          UPDATE_DOCS_GITCOOKIES_GS_PATH, update_docs_gitcookies, api):
    139         with api.context(cwd=api.vars.skia_dir, env=api.infra.go_env):
    140           api.run(api.step, 'Generate and Upload Markdown files', cmd=cmd)
    141 
    142 
    143 def GenTests(api):
    144   fiddleout_no_errors_test_data = """
    145 {"fiddle1": {"fiddleHash": "abc",
    146              "compile_errors": [],
    147              "runtime_error": ""}}
    148 """
    149   fiddleout_with_errors_test_data = """
    150 {"fiddle1": {"fiddleHash": "abc",
    151              "compile_errors": [
    152             {
    153                 "text": "ninja: Entering directory `out/Release'",
    154                 "line": 0,
    155                 "col": 0
    156             },
    157             {
    158                 "text": "[1/7] ACTION //:skia.h(//gn/toolchain:gcc_like)",
    159                 "line": 0,
    160                 "col": 0
    161             },
    162             {
    163                 "text": "[2/7] stamp obj/skia.h.stamp",
    164                 "line": 0,
    165                 "col": 0
    166             },
    167             {
    168                 "text": "[3/7] compile ../../tools/fiddle/draw.cpp",
    169                 "line": 0,
    170                 "col": 0
    171             },
    172             {
    173                 "text": "FAILED: obj/tools/fiddle/fiddle.draw.o ",
    174                 "line": 0,
    175                 "col": 0
    176             },
    177             {
    178                 "text": "c++ -MMD -MF obj/tools/fiddle/fiddle.draw.o.d -DNDEBUG -DSK_HAS_HEIF_LIBRARY -DSK_HAS_JPEG_LIBRARY -DSK_SUPPORT_PDF -DSK_PDF_USE_SFNTLY -DSK_HAS_PNG_LIBRARY -DSK_CODEC_DECODES_RAW -DSK_HAS_WEBP_LIBRARY -DSK_XML -DSK_GAMMA_APPLY_TO_A8 -DSK_ENABLE_DISCRETE_GPU -DGR_TEST_UTILS=1 -DSK_SAMPLES_FOR_X -DSK_SUPPORT_ATLAS_TEXT=1 -I../../tools/flags -I../../include/private -I../../src/c -I../../src/codec -I../../src/core -I../../src/effects -I../../src/fonts -I../../src/image -I../../src/images -I../../src/lazy -I../../src/opts -I../../src/pathops -I../../src/pdf -I../../src/ports -I../../src/sfnt -I../../src/shaders -I../../src/shaders/gradients -I../../src/sksl -I../../src/utils -I../../src/utils/win -I../../src/xml -I../../third_party/gif -I../../src/gpu -I../../tools/gpu -I../../include/android -I../../include/c -I../../include/codec -I../../include/config -I../../include/core -I../../include/effects -I../../include/encode -I../../include/gpu -I../../include/gpu/gl -I../../include/atlastext -I../../include/pathops -I../../include/ports -I../../include/svg -I../../include/utils -I../../include/utils/mac -I../../include/atlastext -Igen -fstrict-aliasing -fPIC -Werror -Wall -Wextra -Winit-self -Wpointer-arith -Wsign-compare -Wvla -Wno-deprecated-declarations -Wno-maybe-uninitialized -Wno-unused-parameter -O3 -fdata-sections -ffunction-sections -g -std=c++11 -fno-exceptions -fno-rtti -Wnon-virtual-dtor -Wno-error -c ../../tools/fiddle/draw.cpp -o obj/tools/fiddle/fiddle.draw.o",
    179                 "line": 0,
    180                 "col": 0
    181             },
    182             {
    183                 "text": "../../tools/fiddle/draw.cpp: In function 'void draw(SkCanvas*)':",
    184                 "line": 0,
    185                 "col": 0
    186             },
    187             {
    188                 "text": "draw.cpp:5:12: error: aggregate 'SkMask mask' has incomplete type and cannot be defined",
    189                 "line": 5,
    190                 "col": 12
    191             },
    192             {
    193                 "text": " }",
    194                 "line": 0,
    195                 "col": 0
    196             },
    197             {
    198                 "text": "            ^   ",
    199                 "line": 0,
    200                 "col": 0
    201             },
    202             {
    203                 "text": "draw.cpp:6:28: error: incomplete type 'SkMask' used in nested name specifier",
    204                 "line": 6,
    205                 "col": 28
    206             },
    207             {
    208                 "text": " ",
    209                 "line": 0,
    210                 "col": 0
    211             },
    212             {
    213                 "text": "                            ^         ",
    214                 "line": 0,
    215                 "col": 0
    216             },
    217             {
    218                 "text": "draw.cpp:14:28: error: incomplete type 'SkMask' used in nested name specifier",
    219                 "line": 14,
    220                 "col": 28
    221             },
    222             {
    223                 "text": "     uint8_t bytes[] = { 0, 1, 2, 3, 4, 5, 6, 7 };",
    224                 "line": 0,
    225                 "col": 0
    226             },
    227             {
    228                 "text": "                            ^~~~~~~~~~",
    229                 "line": 0,
    230                 "col": 0
    231             },
    232             {
    233                 "text": "[4/7] compile ../../tools/fiddle/egl_context.cpp",
    234                 "line": 0,
    235                 "col": 0
    236             },
    237             {
    238                 "text": "[5/7] compile ../../tools/fiddle/fiddle_main.cpp",
    239                 "line": 0,
    240                 "col": 0
    241             },
    242             {
    243                 "text": "[6/7] link libskia.a",
    244                 "line": 0,
    245                 "col": 0
    246             },
    247             {
    248                 "text": "ninja: build stopped: subcommand failed.",
    249                 "line": 0,
    250                 "col": 0
    251             },
    252             {
    253                 "text": "",
    254                 "line": 0,
    255                 "col": 0
    256             }
    257         ],
    258              "runtime_error": ""}}
    259 """
    260   yield (
    261       api.test('percommit_bookmaker') +
    262       api.properties(buildername='Housekeeper-PerCommit-Bookmaker',
    263                      repository='https://skia.googlesource.com/skia.git',
    264                      revision='abc123',
    265                      path_config='kitchen',
    266                      swarm_out_dir='[SWARM_OUT_DIR]')
    267   )
    268 
    269   yield (
    270       api.test('percommit_failed_validation') +
    271       api.properties(buildername='Housekeeper-PerCommit-Bookmaker',
    272                      repository='https://skia.googlesource.com/skia.git',
    273                      revision='abc123',
    274                      path_config='kitchen',
    275                      swarm_out_dir='[SWARM_OUT_DIR]') +
    276       api.step_data('Validate docs match include/core/*.h', retcode=1)
    277   )
    278 
    279   yield (
    280       api.test('nightly_bookmaker') +
    281       api.properties(buildername='Housekeeper-Nightly-Bookmaker',
    282                      repository='https://skia.googlesource.com/skia.git',
    283                      revision='abc123',
    284                      path_config='kitchen',
    285                      fiddleout_test_data=fiddleout_no_errors_test_data,
    286                      swarm_out_dir='[SWARM_OUT_DIR]') +
    287       api.path.exists(api.path['start_dir'].join('fiddleout.json'),
    288                       api.path['start_dir'].join(UPDATE_DOCS_GITCOOKIES_FILE))
    289   )
    290 
    291   yield (
    292       api.test('nightly_failed_fiddles') +
    293       api.properties(buildername='Housekeeper-Nightly-Bookmaker',
    294                      repository='https://skia.googlesource.com/skia.git',
    295                      revision='abc123',
    296                      path_config='kitchen',
    297                      fiddleout_test_data=fiddleout_with_errors_test_data,
    298                      swarm_out_dir='[SWARM_OUT_DIR]') +
    299       api.path.exists(api.path['start_dir'].join('fiddleout.json'))
    300   )
    301 
    302   yield (
    303       api.test('nightly_failed_extract_fiddles') +
    304       api.properties(buildername='Housekeeper-Nightly-Bookmaker',
    305                      repository='https://skia.googlesource.com/skia.git',
    306                      revision='abc123',
    307                      path_config='kitchen',
    308                      swarm_out_dir='[SWARM_OUT_DIR]') +
    309       api.step_data('Extract all fiddles out of md files', retcode=1)
    310   )
    311 
    312   yield (
    313       api.test('nightly_failed_fiddlecli') +
    314       api.properties(buildername='Housekeeper-Nightly-Bookmaker',
    315                      repository='https://skia.googlesource.com/skia.git',
    316                      revision='abc123',
    317                      path_config='kitchen',
    318                      swarm_out_dir='[SWARM_OUT_DIR]') +
    319       api.step_data('Force fiddle to compile all examples', retcode=1)
    320   )
    321 
    322   yield (
    323       api.test('nightly_failed_upload') +
    324       api.properties(buildername='Housekeeper-Nightly-Bookmaker',
    325                      repository='https://skia.googlesource.com/skia.git',
    326                      revision='abc123',
    327                      path_config='kitchen',
    328                      swarm_out_dir='[SWARM_OUT_DIR]') +
    329       api.step_data('Generate and Upload Markdown files', retcode=1)
    330   )
    331