• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Prototiller Requirements for Editions
2
3**Author:** [@mcy](https://github.com/mcy)
4
5**Approved:** 2022-11-29
6
7## Background
8
9Prototiller is Protobuf's new mass refactoring Swiss army knife, similar to
10Buildozer. We plan to use Prototiller to enable LSCs within google3 and to allow
11users (internal and external) to modify `.proto` files safely.
12
13Prototiller is being developed as part of the
14[Editions](../editions/what-are-protobuf-editions.md) project, and will
15prioritize enabling Editions-related refactorings to unblock Editions migrations
16in 2023. This document describes the relevant requirements.
17
18## Overview
19
20*Protochangifier Semantic Actions* (not available externally) describes the
21original design for the Prototiller interface; it would consume a Protobuf
22message that described changes to apply to a `.proto` file passed as input. In
23this document, we prescribe a variant of this interface that fulfills *only* the
24needs of Editions, while remaining extensible for future change actions.
25
26Broad requirements are as follows:
27
28*   Actions must include the following Editions-oriented upgrade workflows:
29    *   Upgrade a file to a particular edition, regardless of whether it's in
30        syntax mode or editions mode, updating features in such a way to be a
31        no-op. **This is the highest-priority workflow.**
32    *   "Clean up" features in a particular file: i.e., run a simple algorithm
33        to determine the smallest set of features that need to be present at
34        each level of the file.
35    *   Modify features from a particular syntax element.
36*   Actions must be both specific to particular syntax elements (for when change
37    specs are checked in alongside `.proto` files by Schema Consumers), and
38    generic (so that a single change spec or set of change specs can power a
39    large-scale change).
40
41In this document we provide a recommendation for a Protobuf schema based on the
42original Protochangifier design, but geared towards these specific needs.
43
44This is only a recommendation; the Prototiller project owners should modify this
45to suit the implementation; only the requirements in this document are binding,
46and the schema is merely an illustration of those requirements.
47
48The suggested schema is as follows.
49
50```
51syntax = "proto2";
52
53package prototiller;
54
55// This is the proto that Prototiller accepts as input.
56message ChangeSpec {
57  // Actions to execute on the file.
58  repeated Action actions = 1;
59
60  // Some changes may result in a wireformat break; changing field type is
61  // usually unsafe. By default, Prototiller does not allow such changes,
62  // users can set allow_unsafe_wire_format_changes to true to force the change.
63  optional bool allow_unsafe_wire_format_changes = 2 [default = false];
64  optional bool allow_unsafe_text_format_changes = 3 [default = false];
65  optional bool allow_unsafe_json_format_changes = 4 [default = false];
66}
67
68// A single action. See messages below for description of their
69// semantics.
70message Action {
71  oneof kind {
72    UpgradeEdition upgrade_edition = 20;
73    CleanUpFeatures clean_up_features = 21;
74    ModifyFeature modify_feature = 22;
75  }
76}
77
78// Upgrades the edition of a file to a specified edition.
79// Treats syntax mode as being a weird, special edition that cannot be
80// upgraded to.
81//
82// This action is always safe.
83message UpgradeEdition {
84  // The edition to upgrade to.
85  optional string edition = 1;
86}
87
88// Cleans up features in a file, such that there are as few explicitly set
89// features as necessary.
90//
91// This action is always safe.
92message CleanUpFeatures {}
93
94// Modifies a specific feature on all syntax elements that match and which can
95// host that particular feature.
96//
97// Prototiller must be aware of which changes affect wire format, so that it
98// can flag them as unsafe.
99message ModifyFeature {
100  // The name of the feature to modify.
101  repeated proto2.UninterpretedOption.NamePart feature = 1;
102
103  // A pattern for matching paths to syntax elements to modify.
104  //
105  // Elements of this field can either be identifiers, or the string "*", which
106  // matches all identifiers. Thus, ["foo", "Bar"] matches the message foo.Bar,
107  // ["foo", "Bar", "*"] matches all fields and nested types of foo.Bar
108  // (recursively), and ["*"] matches all elements of a file.
109  repeated string path_pattern = 2;
110
111  // The value to set the feature to. If not set, this means that the
112  // feature should be deleted.
113  oneof value {
114    int64 int_value = 20;
115    double double_value = 21;
116    // ... and so on.
117  }
118}
119```
120
121## Alternatives Considered
122
123This document does not capture a design so much as requirements that a design
124must satisfy, so we will be brief on potential alternatives to the requirements,
125and why we decided against them.
126
127*   Omit feature cleanup as its own action, and let it happen implicitly as part
128    of other actions.
129    *   It is desirable to be able to aggressively run this operation
130        everywhere, potentially even as part of "format on save" in Cider and
131        other IDEs.
132*   Make `ModifyFeature` operate on all syntax elements of a file
133    simultaneously.
134    *   `ModifyFeature` is intended so that SchemaConsumers can affect
135        fine-grained control of features in `.proto` files they import. Users
136        will want to be able to wipe out a feature from all fields in a file, or
137        perhaps just on a handful of fields they care about. Offering simple
138        pattern-matching supports both.
139