xref: /aosp_15_r20/external/google-cloud-java/owl-bot-postprocessor/synthtool/README.md (revision 55e87721aa1bc457b326496a7ca40f3ea1a63287)
1*55e87721SMatt Gilbride# SynthTool (for client libraries)
2*55e87721SMatt Gilbride
3*55e87721SMatt Gilbride![Diagram of relationship between Autosynth, Synthtool, and Github](../images/flow.png)
4*55e87721SMatt Gilbride
5*55e87721SMatt GilbrideThis tool helps to generate and layout cloud client libraries. Synthtool runs the [GAPIC (Generated API Client) Generator][GAPIC] via [Google API Artifact Manager (artman)][artman].
6*55e87721SMatt Gilbride
7*55e87721SMatt Gilbride[GAPIC]: https://github.com/googleapis/gapic-generator
8*55e87721SMatt Gilbride[artman]: https://github.com/googleapis/artman
9*55e87721SMatt Gilbride
10*55e87721SMatt Gilbride## Prerequisites
11*55e87721SMatt Gilbride
12*55e87721SMatt Gilbride1. **Linux**  This tool runs on Linux only.  No other platforms are supported.
13*55e87721SMatt Gilbride
14*55e87721SMatt Gilbride2. **Python 3.6** Either install it from [python.org][python_downloads] or use
15*55e87721SMatt Gilbride[pyenv][] to get 3.6.
16*55e87721SMatt Gilbride
17*55e87721SMatt Gilbride3. **Bazel**  can be downloaded from [bazel.build](https://bazel.build/).
18*55e87721SMatt Gilbride
19*55e87721SMatt Gilbride4. **Docker**  Some synth.py files require [Docker] to generate code.
20*55e87721SMatt Gilbride
21*55e87721SMatt Gilbride5. Clone this repository and install this library with pip:
22*55e87721SMatt Gilbride
23*55e87721SMatt Gilbride    ```
24*55e87721SMatt Gilbride    cd synthtool
25*55e87721SMatt Gilbride    python3 -m pip install -e .
26*55e87721SMatt Gilbride    ```
27*55e87721SMatt Gilbride
28*55e87721SMatt Gilbride
29*55e87721SMatt Gilbride[python_downloads]: https://www.python.org/downloads/
30*55e87721SMatt Gilbride[pyenv]: https://github.com/pyenv/pyenv
31*55e87721SMatt Gilbride[Docker]: https://docs.docker.com/v17.09/engine/installation/#desktop
32*55e87721SMatt Gilbride
33*55e87721SMatt Gilbride
34*55e87721SMatt Gilbride## Basic usage
35*55e87721SMatt GilbrideTo start the process of generation, clone the destination repository.
36*55e87721SMatt Gilbride```
37*55e87721SMatt Gilbridegit clone [email protected]:googleapis/python-tasks.git
38*55e87721SMatt Gilbridecd python-tasks/
39*55e87721SMatt Gilbride```
40*55e87721SMatt Gilbride
41*55e87721SMatt Gilbride### Running `synthtool`
42*55e87721SMatt GilbrideIf a `synth.py` script is not present, create a new one.
43*55e87721SMatt Gilbride
44*55e87721SMatt GilbrideYou can create one from scratch or copy one from another library.
45*55e87721SMatt Gilbride - e.g. the `synth.py` for the Cloud Tasks API for [Python][python_tasks_synth_py],
46*55e87721SMatt Gilbride[Java][java_tasks_synth_py], [Node.js][node_tasks_synth_py], [PHP][php_tasks_synth_py],
47*55e87721SMatt Gilbrideor [Ruby][ruby_tasks_synth_py].
48*55e87721SMatt Gilbride
49*55e87721SMatt GilbrideRun `synthtool`:
50*55e87721SMatt Gilbride
51*55e87721SMatt Gilbride```
52*55e87721SMatt Gilbridepython3 -m synthtool
53*55e87721SMatt Gilbride```
54*55e87721SMatt Gilbride
55*55e87721SMatt GilbrideAfter `synthtool` runs successfully:
56*55e87721SMatt Gilbride - Investigate the changes it made
57*55e87721SMatt Gilbride - Run the library tests
58*55e87721SMatt Gilbride - Commit and push the changes to a branch and open a Pull Request
59*55e87721SMatt Gilbride
60*55e87721SMatt GilbrideFind examples below in different programming languages (Cloud Tasks API used as an example).
61*55e87721SMatt Gilbride
62*55e87721SMatt Gilbride### Python
63*55e87721SMatt Gilbride- Clone the destination repository:
64*55e87721SMatt Gilbride  ```
65*55e87721SMatt Gilbride  git clone [email protected]:googleapis/python-tasks.git
66*55e87721SMatt Gilbride  cd python-tasks/
67*55e87721SMatt Gilbride  ```
68*55e87721SMatt Gilbride- Run `synthtool` to generate using the existing [`synth.py`][python_tasks_synth_py]
69*55e87721SMatt Gilbride  file for the [Python Client for Cloud Tasks API][python_tasks_library]:
70*55e87721SMatt Gilbride  ```
71*55e87721SMatt Gilbride  python3 -m synthtool
72*55e87721SMatt Gilbride  ```
73*55e87721SMatt Gilbride- See the Python [Contributing Guide][python_contributing]
74*55e87721SMatt Gilbride  or instructions to install dependencies, run tests, and submit a contribution.
75*55e87721SMatt Gilbride
76*55e87721SMatt Gilbride[python_tasks_library]: https://github.com/googleapis/python-tasks
77*55e87721SMatt Gilbride[python_tasks_synth_py]: https://github.com/googleapis/python-tasks/blob/master/synth.py
78*55e87721SMatt Gilbride[python_contributing]: https://github.com/googleapis/python-tasks/blob/master/CONTRIBUTING.rst
79*55e87721SMatt Gilbride
80*55e87721SMatt Gilbride### Java
81*55e87721SMatt Gilbride- Clone the destination repository:
82*55e87721SMatt Gilbride  ```
83*55e87721SMatt Gilbride  git clone [email protected]:googleapis/java-tasks.git
84*55e87721SMatt Gilbride  cd java-tasks/
85*55e87721SMatt Gilbride  ```
86*55e87721SMatt Gilbride- Run `synthtool` to generate using the existing [`synth.py`][java_tasks_synth_py]
87*55e87721SMatt Gilbride  file for the [Google Cloud Java Client for Cloud Tasks][java_tasks_library]:
88*55e87721SMatt Gilbride  ```
89*55e87721SMatt Gilbride  python3 -m synthtool
90*55e87721SMatt Gilbride  ```
91*55e87721SMatt Gilbride- See the Java [Contributing Guide][java_contributing]
92*55e87721SMatt Gilbride  or instructions to install dependencies, run tests, and submit a contribution.
93*55e87721SMatt Gilbride
94*55e87721SMatt Gilbride[java_tasks_library]: https://github.com/googleapis/java-tasks
95*55e87721SMatt Gilbride[java_tasks_synth_py]: https://github.com/googleapis/java-tasks/blob/master/synth.py
96*55e87721SMatt Gilbride[java_contributing]: https://github.com/googleapis/java-tasks/blob/master/CONTRIBUTING.md
97*55e87721SMatt Gilbride
98*55e87721SMatt Gilbride### Node.js
99*55e87721SMatt Gilbride- Clone the destination repository:
100*55e87721SMatt Gilbride  ```
101*55e87721SMatt Gilbride  git clone [email protected]:googleapis/nodejs-tasks.git
102*55e87721SMatt Gilbride  cd nodejs-tasks/
103*55e87721SMatt Gilbride  ```
104*55e87721SMatt Gilbride- Run `synthtool` to generate using the existing [`synth.py`][node_tasks_synth_py]
105*55e87721SMatt Gilbride  file for the [Google Cloud Tasks Node.js Client][node_tasks_library]:
106*55e87721SMatt Gilbride  ```
107*55e87721SMatt Gilbride  python3 -m synthtool
108*55e87721SMatt Gilbride  ```
109*55e87721SMatt Gilbride- See the Node.js [Contributing Guide][node_tasks_contributing]
110*55e87721SMatt Gilbride  or instructions to install dependencies, run tests, and submit a contribution.
111*55e87721SMatt Gilbride
112*55e87721SMatt Gilbride[node_tasks_library]: https://github.com/googleapis/nodejs-tasks
113*55e87721SMatt Gilbride[node_tasks_synth_py]: https://github.com/googleapis/nodejs-tasks/blob/master/synth.py
114*55e87721SMatt Gilbride[node_tasks_contributing]: https://github.com/googleapis/nodejs-tasks/blob/master/CONTRIBUTING.md
115*55e87721SMatt Gilbride
116*55e87721SMatt Gilbride### PHP
117*55e87721SMatt Gilbride- Clone the destination repository:
118*55e87721SMatt Gilbride  ```
119*55e87721SMatt Gilbride  git clone [email protected]:googleapis/google-cloud-php.git
120*55e87721SMatt Gilbride  cd google-cloud-php/
121*55e87721SMatt Gilbride  ```
122*55e87721SMatt Gilbride- Navigate to the destination directory:
123*55e87721SMatt Gilbride  ```
124*55e87721SMatt Gilbride  cd Tasks/
125*55e87721SMatt Gilbride  ```
126*55e87721SMatt Gilbride- Run `synthtool` to generate using the existing [`synth.py`][php_tasks_synth_py]
127*55e87721SMatt Gilbride  file for the [Google Cloud Tasks client for PHP][php_tasks_library]:
128*55e87721SMatt Gilbride  ```
129*55e87721SMatt Gilbride  python3 -m synthtool
130*55e87721SMatt Gilbride  ```
131*55e87721SMatt Gilbride- See the PHP [Contributing Guide][php_contributing]
132*55e87721SMatt Gilbride  or instructions to install dependencies, run tests, and submit a contribution.
133*55e87721SMatt Gilbride
134*55e87721SMatt Gilbride[php_tasks_library]: https://github.com/googleapis/google-cloud-php/tree/master/Tasks
135*55e87721SMatt Gilbride[php_tasks_synth_py]: https://github.com/googleapis/google-cloud-php/blob/master/Tasks/synth.py
136*55e87721SMatt Gilbride[php_contributing]: https://github.com/googleapis/google-cloud-php/blob/master/CONTRIBUTING.md
137*55e87721SMatt Gilbride
138*55e87721SMatt Gilbride### Ruby
139*55e87721SMatt Gilbride- Clone the destination repository:
140*55e87721SMatt Gilbride  ```
141*55e87721SMatt Gilbride  git clone [email protected]:googleapis/google-cloud-ruby.git
142*55e87721SMatt Gilbride  cd google-cloud-ruby/
143*55e87721SMatt Gilbride  ```
144*55e87721SMatt Gilbride- Navigate to the destination directory:
145*55e87721SMatt Gilbride  ```
146*55e87721SMatt Gilbride  cd google-cloud-tasks/
147*55e87721SMatt Gilbride  ```
148*55e87721SMatt Gilbride- Run `synthtool` to generate using the existing [`synth.py`][ruby_tasks_synth_py]
149*55e87721SMatt Gilbride  file for the [Ruby Client for Cloud Tasks API][ruby_tasks_library]:
150*55e87721SMatt Gilbride  ```
151*55e87721SMatt Gilbride  python3 -m synthtool
152*55e87721SMatt Gilbride  ```
153*55e87721SMatt Gilbride- See the Ruby [Contributing Guide][ruby_contributing]
154*55e87721SMatt Gilbride  or instructions to install dependencies, run tests, and submit a contribution.
155*55e87721SMatt Gilbride
156*55e87721SMatt Gilbride[ruby_tasks_library]: https://github.com/googleapis/google-cloud-ruby/tree/master/google-cloud-tasks
157*55e87721SMatt Gilbride[ruby_tasks_synth_py]: https://github.com/googleapis/google-cloud-ruby/blob/master/google-cloud-tasks/synth.py
158*55e87721SMatt Gilbride[ruby_contributing]: https://github.com/googleapis/google-cloud-ruby/blob/master/.github/CONTRIBUTING.md
159*55e87721SMatt Gilbride
160*55e87721SMatt Gilbride## Features
161*55e87721SMatt Gilbride
162*55e87721SMatt Gilbride### Common transforms
163*55e87721SMatt Gilbride
164*55e87721SMatt GilbrideFunctions in synthtool make it easier to copy files, merge files, etc.
165*55e87721SMatt GilbrideSee the [pydocs](https://htmlpreview.github.io/?https://github.com/googleapis/synthtool/blob/master/synthtool/pydoc.html) for more details.
166*55e87721SMatt Gilbride
167*55e87721SMatt Gilbride### Templating
168*55e87721SMatt GilbrideSynthTool supports template files using [Jinja](http://jinja.pocoo.org/).
169*55e87721SMatt Gilbride
170*55e87721SMatt GilbrideTemplates are found in subdirectories of [`synthtool/gcp/templates/`](gcp/templates/)
171*55e87721SMatt Gilbridefor each language,
172*55e87721SMatt Gilbride - e.g. the template directories for [Python][python_templates],
173*55e87721SMatt Gilbride[Node.js][node_templates], [PHP][php_templates], or [Ruby][ruby_templates].
174*55e87721SMatt Gilbride
175*55e87721SMatt Gilbride[python_templates]: gcp/templates/python_library/
176*55e87721SMatt Gilbride[node_templates]: gcp/templates/node_library/
177*55e87721SMatt Gilbride[php_templates]: gcp/templates/php_library/
178*55e87721SMatt Gilbride[ruby_templates]:  gcp/templates/ruby_library/
179*55e87721SMatt Gilbride
180*55e87721SMatt GilbrideYou can generate and copy templates using `gcp.CommonTemplates` in your `synth.py`:
181*55e87721SMatt Gilbride```py
182*55e87721SMatt Gilbridecommon_templates = gcp.CommonTemplates()
183*55e87721SMatt Gilbride
184*55e87721SMatt Gilbridetemplates = common_templates.node_library()
185*55e87721SMatt Gilbrides.copy(templates)
186*55e87721SMatt Gilbride```
187*55e87721SMatt Gilbride
188*55e87721SMatt GilbrideYou can provide variables to templates as keyword arguments to the library generation method:
189*55e87721SMatt Gilbride
190*55e87721SMatt Gilbride```py
191*55e87721SMatt Gilbridecommon_templates = gcp.CommonTemplates()
192*55e87721SMatt Gilbride
193*55e87721SMatt Gilbridetemplates = common_templates.node_library(version=5, show_version=True, previous_versions=[1,2,3,4])
194*55e87721SMatt Gilbride
195*55e87721SMatt Gilbrides.copy(templates)
196*55e87721SMatt Gilbride```
197*55e87721SMatt Gilbride
198*55e87721SMatt GilbrideTemplate files can access any values provided, e.g.
199*55e87721SMatt Gilbride - `README.md.j2`
200*55e87721SMatt Gilbride    ```py
201*55e87721SMatt Gilbride    {% if show_version %}
202*55e87721SMatt Gilbride    The version is {{ version }}
203*55e87721SMatt Gilbride
204*55e87721SMatt Gilbride    {% if previous versions is defined %}
205*55e87721SMatt Gilbride    Previous versions:
206*55e87721SMatt Gilbride      {% for ver in previous_versions %}
207*55e87721SMatt Gilbride      - {{ ver }}
208*55e87721SMatt Gilbride      {% endfor %}
209*55e87721SMatt Gilbride    {% endif %}
210*55e87721SMatt Gilbride    {% endif %}
211*55e87721SMatt Gilbride    ```
212*55e87721SMatt Gilbride
213*55e87721SMatt GilbrideFor more information on how to use Synthtool templating for Python Samples, view [/py_templating_instructions](./py_templating_instructions)
214*55e87721SMatt Gilbride
215*55e87721SMatt GilbrideYou can learn more about Jinga templating in the
216*55e87721SMatt Gilbride[Template Designer Documentation](http://jinja.pocoo.org/docs/templates/).
217*55e87721SMatt Gilbride
218*55e87721SMatt Gilbride### googleapis-private
219*55e87721SMatt GilbrideSynthTool supports generation from googleapis/googleapis-private.
220*55e87721SMatt Gilbride
221*55e87721SMatt Gilbride```py
222*55e87721SMatt Gilbridegapic = gcp.GAPICGenerator()
223*55e87721SMatt Gilbride
224*55e87721SMatt Gilbridelibrary = gapic.node_library('speech', 'v1', private=True)
225*55e87721SMatt Gilbride```
226*55e87721SMatt Gilbride2FA is required to clone a private repo.
227*55e87721SMatt Gilbride
228*55e87721SMatt Gilbride* **Using SSH:** Before running Synthtool, set the environment variable `AUTOSYNTH_USE_SSH` to `true`.
229*55e87721SMatt Gilbride
230*55e87721SMatt GilbrideThe repo is cloned using SSH.
231*55e87721SMatt Gilbride* **Using HTTPS:** Generate a [GitHub Personal Access Token](https://github.com/settings/tokens) with scope `repo`.
232*55e87721SMatt GilbrideRun `synthtool`.
233*55e87721SMatt Gilbride
234*55e87721SMatt GilbrideWhen GitHub prompts for your GitHub password, provide the access token instead.
235*55e87721SMatt Gilbride
236*55e87721SMatt Gilbride```
237*55e87721SMatt Gilbridesynthtool > Cloning googleapis-private.
238*55e87721SMatt GilbrideUsername for 'https://github.com': busunkim96
239*55e87721SMatt GilbridePassword for 'https://[email protected]':
240*55e87721SMatt Gilbride```
241*55e87721SMatt Gilbride
242*55e87721SMatt Gilbride### Artman Version
243*55e87721SMatt GilbrideSynthTool uses the latest version of the [Artman Docker image](https://hub.docker.com/r/googleapis/artman).
244*55e87721SMatt GilbrideYou can change this by setting the environment variable `SYNTHTOOL_ARTMAN_VERSION` to the desired version tag.
245*55e87721SMatt Gilbride
246*55e87721SMatt Gilbride```
247*55e87721SMatt Gilbrideexport SYNTHTOOL_ARTMAN_VERSION=0.16.2
248*55e87721SMatt Gilbride```
249*55e87721SMatt Gilbride
250*55e87721SMatt Gilbride### GAPIC Generator Python Version
251*55e87721SMatt GilbrideSynthTool uses the latest version of [gcr.io/gapic-images/gapic-generator-python](https://gcr.io/gapic-images/gapic-generator-python). You can change this by
252*55e87721SMatt Gilbridesetting the environment variable `SYNTHTOOL_GAPIC_GENERATOR_PYTHON_VERSION` to the desired version tag.
253*55e87721SMatt Gilbride
254*55e87721SMatt Gilbride```
255*55e87721SMatt Gilbrideexport SYNTHTOOL_GAPIC_GENERATOR_PYTHON_VERSION=0.22.0
256*55e87721SMatt Gilbride```
257*55e87721SMatt Gilbride
258*55e87721SMatt GilbrideAlternatively you can set the generator version by passing it to `gapic.py_library`.
259*55e87721SMatt Gilbride
260*55e87721SMatt Gilbride```python
261*55e87721SMatt Gilbrideimport synthtool as s
262*55e87721SMatt Gilbrideimport synthtool.gcp as gcp
263*55e87721SMatt Gilbride
264*55e87721SMatt Gilbridegapic = gcp.GAPICMicrogenerator()
265*55e87721SMatt Gilbride
266*55e87721SMatt Gilbridelibrary = gapic.py_library(
267*55e87721SMatt Gilbride    "bigquery/connection", "v1beta1", generator_version="0.22.0"
268*55e87721SMatt Gilbride)
269*55e87721SMatt Gilbride```
270*55e87721SMatt Gilbride
271*55e87721SMatt Gilbride### Local Googleapis
272*55e87721SMatt GilbrideSynthTool supports generation from a local copy of googleapis.
273*55e87721SMatt GilbrideSpecify the path to `googleapis` in the environment variable `SYNTHTOOL_GOOGLEAPIS`.
274*55e87721SMatt Gilbride
275*55e87721SMatt Gilbride```
276*55e87721SMatt Gilbrideexport SYNTHTOOL_GOOGLEAPIS=path/to/local/googleapis
277*55e87721SMatt Gilbride```
278*55e87721SMatt Gilbride
279*55e87721SMatt Gilbride### Local GAPIC Generator
280*55e87721SMatt GilbrideSynthTool supports generation from a local copy of [gapic-generator](https://github.com/googleapis/gapic-generator).
281*55e87721SMatt GilbrideSpecify the path to `gapic-generator` in the environment variable `SYNTHTOOL_GENERATOR`.
282*55e87721SMatt Gilbride
283*55e87721SMatt Gilbride```
284*55e87721SMatt Gilbrideexport SYNTHTOOL_GENERATOR=path/to/local/gapic-generator
285*55e87721SMatt Gilbride```
286*55e87721SMatt Gilbride
287*55e87721SMatt GilbrideDon't forget to compile `gapic-generator` before running SynthTool.
288*55e87721SMatt Gilbride
289*55e87721SMatt Gilbride```
290*55e87721SMatt Gilbridecd path/to/local/gapic-generator
291*55e87721SMatt Gilbride./gradlew fatJar
292*55e87721SMatt Gilbride```
293*55e87721SMatt Gilbride
294*55e87721SMatt Gilbride### Local Template Files
295*55e87721SMatt GilbrideSynthTool supports specifying a local directory of templates. Specify the path to the root
296*55e87721SMatt Gilbridetemplate directory (not a SynthTool clone) in the environment variable `SYNTHTOOL_TEMPLATES`.
297*55e87721SMatt Gilbride
298*55e87721SMatt Gilbride```
299*55e87721SMatt Gilbrideexport SYNTHTOOL_TEMPLATES=path/to/local/templates
300*55e87721SMatt Gilbride```
301*55e87721SMatt Gilbride
302*55e87721SMatt Gilbride### Include .proto files
303*55e87721SMatt GilbrideSynthTool supports copying .proto API definition files from googleapis.
304*55e87721SMatt Gilbride
305*55e87721SMatt Gilbride```py
306*55e87721SMatt Gilbridegapic = gcp.GAPICGenerator()
307*55e87721SMatt Gilbride
308*55e87721SMatt Gilbridelibrary = gapic.node_library('speech', 'v1', include_protos=True)
309*55e87721SMatt Gilbride```
310*55e87721SMatt Gilbride
311*55e87721SMatt Gilbride## Context-Aware Commits
312*55e87721SMatt Gilbride
313*55e87721SMatt GilbrideAutosynth runs synthtool on your `synth.py` nightly or more frequently.
314*55e87721SMatt GilbrideBy default, it runs synthtool once, and if the generated code differs,
315*55e87721SMatt Gilbridecreates a PR with the differences.
316*55e87721SMatt Gilbride
317*55e87721SMatt GilbrideAutosynth can also find which changes in upstream repositories triggered changes
318*55e87721SMatt Gilbridein the generated code.  To enable this behavior (context-aware commits),
319*55e87721SMatt Gilbrideset one or both of the following flags in you synth.py file:
320*55e87721SMatt Gilbride
321*55e87721SMatt Gilbride```py
322*55e87721SMatt GilbrideAUTOSYNTH_MULTIPLE_COMMITS
323*55e87721SMatt GilbrideAUTOSYNTH_MULTIPLE_PRS
324*55e87721SMatt Gilbride```
325*55e87721SMatt Gilbride
326*55e87721SMatt Gilbride### Example
327*55e87721SMatt Gilbride
328*55e87721SMatt GilbrideAssume that since the library source code was last generated, A, B and X, Y
329*55e87721SMatt Gilbridewere committed to googleapis and synthtool respectively, and they all triggered
330*55e87721SMatt Gilbridechanges in the generated library code.
331*55e87721SMatt Gilbride
332*55e87721SMatt Gilbride| [googleapis](https://github.com/googleapis/googleapis) | [synthtool (templates)](gcp/templates) |
333*55e87721SMatt Gilbride| :--------: | :-------------------: |
334*55e87721SMatt Gilbride|  A         |  X                    |
335*55e87721SMatt Gilbride|  B         |  Y                    |
336*55e87721SMatt Gilbride
337*55e87721SMatt Gilbride
338*55e87721SMatt GilbrideHere's what autosynth generates for each flag setting.
339*55e87721SMatt Gilbride
340*55e87721SMatt Gilbride```py
341*55e87721SMatt GilbrideAUTOSYNTH_MULTIPLE_COMMITS = True
342*55e87721SMatt Gilbride```
343*55e87721SMatt Gilbride
344*55e87721SMatt GilbrideAutosynth creates one PR, with a single commit for each original commit:
345*55e87721SMatt Gilbride| PR |
346*55e87721SMatt Gilbride| - |
347*55e87721SMatt Gilbride| A |
348*55e87721SMatt Gilbride| B |
349*55e87721SMatt Gilbride| X |
350*55e87721SMatt Gilbride| Y |
351*55e87721SMatt Gilbride
352*55e87721SMatt Gilbride***
353*55e87721SMatt Gilbride
354*55e87721SMatt Gilbride```py
355*55e87721SMatt GilbrideAUTOSYNTH_MULTIPLE_COMMITS = True
356*55e87721SMatt GilbrideAUTOSYNTH_MULTIPLE_PRS = True
357*55e87721SMatt Gilbride```
358*55e87721SMatt Gilbride
359*55e87721SMatt GilbrideAutosynth creates two PRs, with a single commit for each original commit:
360*55e87721SMatt Gilbride| PR1 |
361*55e87721SMatt Gilbride| - |
362*55e87721SMatt Gilbride| A |
363*55e87721SMatt Gilbride| B |
364*55e87721SMatt Gilbride
365*55e87721SMatt Gilbride| PR2 |
366*55e87721SMatt Gilbride| - |
367*55e87721SMatt Gilbride| X |
368*55e87721SMatt Gilbride| Y |
369*55e87721SMatt Gilbride
370*55e87721SMatt Gilbride
371*55e87721SMatt Gilbride***
372*55e87721SMatt Gilbride
373*55e87721SMatt Gilbride```py
374*55e87721SMatt GilbrideAUTOSYNTH_MULTIPLE_PRS = True
375*55e87721SMatt Gilbride```
376*55e87721SMatt Gilbride
377*55e87721SMatt GilbrideAutosynth creates two PRs, with a single commit combining all the
378*55e87721SMatt Gilbrideoriginal commits.
379*55e87721SMatt Gilbride
380*55e87721SMatt Gilbride| PR1 |
381*55e87721SMatt Gilbride| - |
382*55e87721SMatt Gilbride| AB |
383*55e87721SMatt Gilbride
384*55e87721SMatt Gilbride| PR2 |
385*55e87721SMatt Gilbride| - |
386*55e87721SMatt Gilbride| XY |
387*55e87721SMatt Gilbride
388*55e87721SMatt Gilbride
389*55e87721SMatt Gilbride## Helpful tips
390*55e87721SMatt Gilbride### Where does the generated code go?
391*55e87721SMatt GilbrideSynthTool runs [Artman](https://hub.docker.com/r/googleapis/artman) which creates generated code that
392*55e87721SMatt Gilbridecan be found at `~/.cache/synthtool/googleapis<-private>/artman_genfiles`. This is useful for figuring out
393*55e87721SMatt Gilbridewhat it is you need to copy for your specific library.
394*55e87721SMatt Gilbride
395*55e87721SMatt Gilbride### Warning: Don't lint manually-written code in synth.py!
396*55e87721SMatt Gilbride
397*55e87721SMatt GilbrideBen had the misfortune to discover a corner case where autosynth deleted a file that Ben never intended or expected it to delete.
398*55e87721SMatt Gilbride
399*55e87721SMatt GilbrideHere is what happened:
400*55e87721SMatt Gilbride
401*55e87721SMatt Gilbride1. Autosynth cannot directly observe which files your synth.py generates, because synth.py could literally do anything, including launch the space shuttle.  So, Autosynth figures out which files were generated by examining all the file system reads and writes that happened while synth.py was executing.  Any file that is written to or copied to is deemed to have been generated by synth.py and recorded as a generatedFiles in synth.metadata.
402*55e87721SMatt Gilbride
403*55e87721SMatt Gilbride2. NodeJS's synth.py ran the linter on manually-written sample files in the repo.  A new version of the linter was pulled in, which modified a manually-written sample file.  Autosynth observed the write and concluded that the manually-written file was a generated file, and listed it in generatedFiles in synth.metadata.  The next time Autosynth ran, the linter made no changes, and the manually-written sample file was not written to.  Autosynth concluded the manually-written sample file was no longer being generated, and deleted it.
404*55e87721SMatt Gilbride
405*55e87721SMatt Gilbride#### Lesson Learned:
406*55e87721SMatt GilbrideMake sure your synth.py does not touch any manually-written files in the repo.
407