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_steps() 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 = [] 107 for fiddle_name in out: 108 props = out[fiddle_name] 109 if props['compile_errors'] or props['runtime_error']: 110 failing_fiddles.append(props['fiddleHash']) 111 if failing_fiddles: 112 # create an eror message and fail the bot! 113 failure_msg = 'The following fiddles failed:\n\n' 114 for fiddle_hash in failing_fiddles: 115 failure_msg += 'https://fiddle.skia.org/c/%s\n' % fiddle_hash 116 raise api.step.StepFailure(failure_msg) 117 118 # Step 4: Update docs in site/user/api/ with the output of fiddlecli. 119 # If there are any new changes then upload and commit the changes. 120 update_docs_gitcookies = api.path['start_dir'].join( 121 UPDATE_DOCS_GITCOOKIES_FILE) 122 cmd = ['python', 123 api.vars.skia_dir.join('infra', 'bots', 'upload_md.py'), 124 '--bookmaker_binary', bookmaker_binary, 125 '--fiddlecli_output', fiddlecli_output, 126 '--gitcookies', str(update_docs_gitcookies)] 127 with api.infra.DownloadGitCookies( 128 UPDATE_DOCS_GITCOOKIES_GS_PATH, update_docs_gitcookies, api): 129 with api.context(cwd=api.vars.skia_dir, env=api.infra.go_env): 130 api.run(api.step, 'Generate and Upload Markdown files', cmd=cmd) 131 132 133 def GenTests(api): 134 fiddleout_no_errors_test_data = """ 135 {"fiddle1": {"fiddleHash": "abc", 136 "compile_errors": [], 137 "runtime_error": ""}} 138 """ 139 fiddleout_with_errors_test_data = """ 140 {"fiddle1": {"fiddleHash": "abc", 141 "compile_errors": [], 142 "runtime_error": "runtime error"}} 143 """ 144 yield ( 145 api.test('percommit_bookmaker') + 146 api.properties(buildername='Housekeeper-PerCommit-Bookmaker', 147 repository='https://skia.googlesource.com/skia.git', 148 revision='abc123', 149 path_config='kitchen', 150 swarm_out_dir='[SWARM_OUT_DIR]') 151 ) 152 153 yield ( 154 api.test('percommit_failed_validation') + 155 api.properties(buildername='Housekeeper-PerCommit-Bookmaker', 156 repository='https://skia.googlesource.com/skia.git', 157 revision='abc123', 158 path_config='kitchen', 159 swarm_out_dir='[SWARM_OUT_DIR]') + 160 api.step_data('Validate docs match include/core/*.h', retcode=1) 161 ) 162 163 yield ( 164 api.test('nightly_bookmaker') + 165 api.properties(buildername='Housekeeper-Nightly-Bookmaker', 166 repository='https://skia.googlesource.com/skia.git', 167 revision='abc123', 168 path_config='kitchen', 169 fiddleout_test_data=fiddleout_no_errors_test_data, 170 swarm_out_dir='[SWARM_OUT_DIR]') + 171 api.path.exists(api.path['start_dir'].join('fiddleout.json'), 172 api.path['start_dir'].join(UPDATE_DOCS_GITCOOKIES_FILE)) 173 ) 174 175 yield ( 176 api.test('nightly_failed_fiddles') + 177 api.properties(buildername='Housekeeper-Nightly-Bookmaker', 178 repository='https://skia.googlesource.com/skia.git', 179 revision='abc123', 180 path_config='kitchen', 181 fiddleout_test_data=fiddleout_with_errors_test_data, 182 swarm_out_dir='[SWARM_OUT_DIR]') + 183 api.path.exists(api.path['start_dir'].join('fiddleout.json')) 184 ) 185 186 yield ( 187 api.test('nightly_failed_extract_fiddles') + 188 api.properties(buildername='Housekeeper-Nightly-Bookmaker', 189 repository='https://skia.googlesource.com/skia.git', 190 revision='abc123', 191 path_config='kitchen', 192 swarm_out_dir='[SWARM_OUT_DIR]') + 193 api.step_data('Extract all fiddles out of md files', retcode=1) 194 ) 195 196 yield ( 197 api.test('nightly_failed_fiddlecli') + 198 api.properties(buildername='Housekeeper-Nightly-Bookmaker', 199 repository='https://skia.googlesource.com/skia.git', 200 revision='abc123', 201 path_config='kitchen', 202 swarm_out_dir='[SWARM_OUT_DIR]') + 203 api.step_data('Force fiddle to compile all examples', retcode=1) 204 ) 205 206 yield ( 207 api.test('nightly_failed_upload') + 208 api.properties(buildername='Housekeeper-Nightly-Bookmaker', 209 repository='https://skia.googlesource.com/skia.git', 210 revision='abc123', 211 path_config='kitchen', 212 swarm_out_dir='[SWARM_OUT_DIR]') + 213 api.step_data('Generate and Upload Markdown files', retcode=1) 214 ) 215