1 | # Project Editors
|
2 | Project editors are functions that can modify a project.
|
3 |
|
4 | They are usually invoked from [command handlers](CommandHandlers.md). Project editors are also used to implement [project generators](ProjectGenerators.md).
|
5 |
|
6 | To edit one project, specify:
|
7 |
|
8 | - GitHub credentials: see [Secrets](commands.md#secrets) for how to do this operation as the user who invoked the command,
|
9 | - How to edit the project: Atomist uses a [Project](https://atomist.github.io/automation-client-ts/modules/_project_project_.html)
|
10 | object to model operations on a repository; pass a function that changes it.
|
11 | - How to save your work: make a [Pull Request](https://atomist.github.io/automation-client-ts/classes/_operations_edit_editmodes_.pullrequest.html)
|
12 | or [commit to a branch](https://atomist.github.io/automation-client-ts/interfaces/_operations_edit_editmodes_.branchcommit.html).
|
13 | - which repository to edit: see [Mapped Parameters](commands/#mapped-parameters)
|
14 | for how to guess this from the channel where the command is invoked.
|
15 |
|
16 |
|
17 | The `handle` method contains of a project editor command to add a CONTRIBUTING.md file might look like:
|
18 |
|
19 | ```typescript
|
20 | function editProject(p: Project) {
|
21 | return p.addFile("CONTRIBUTING.md", `Yes! Contributions are welcome`)
|
22 | }
|
23 |
|
24 | const pullRequest = new PullRequest("contributing", "Add CONTRIBUTING.md");
|
25 |
|
26 | const gitHubRepo = new GitHubRepoRef(this.owner, this.repository);
|
27 |
|
28 | return editOne(context,
|
29 | { token: this.githubToken }, // GitHub credentials
|
30 | editProject, // a function to change the project
|
31 | pullRequest, // how to save the edit
|
32 | gitHubRepo) // where to find the project
|
33 | .then(success, failure);
|
34 | ```
|
35 |
|
36 | Check [the complete source](https://github.com/atomist/automation-client-samples-ts/tree/master/src/commands/editor/AddContributing.ts) for the necessary imports.
|
37 |
|
38 | ## Edit across repositories
|
39 |
|
40 | You can update all your repositories at once!
|
41 |
|
42 | You need a function to edit the project. This one gets the project, the HandlerContext and some additional parameters.
|
43 | It returns an EditResult.
|
44 |
|
45 | ```typescript
|
46 | export function editProject(p: Project, context: HandlerContext, params: { newYear: string }): Promise<EditResult> {
|
47 | return p.findFile("README.md")
|
48 | .then(file => file.replace(/(Copyright.*\s)[0-9]+(\s+Atomist)/, `$1${params.newYear}$2`))
|
49 | .then(() => successfulEdit(p), (err) => failedEdit(p, err));
|
50 | }
|
51 | ```
|
52 |
|
53 | Then in the handle method, use `editAll` to run on all the projects that Atomist can find:
|
54 |
|
55 | ```typescript
|
56 | return editAll(context,
|
57 | { token: this.githubToken }, // GitHub credentials
|
58 | editProject, // how to change the project
|
59 | new PullRequest("update-copyright-year", "Update the copyright to " + this.newYear), // how to save the edit
|
60 | { newYear: this.newYear }) // parameters to pass on to the edit function
|
61 | .then(success, failure);
|
62 | ```
|
63 |
|
64 | Find the [complete example here](https://github.com/atomist/automation-client-samples-ts/tree/master/src/cs/editor/UpdateCopyright.ts)
|
65 |
|
66 |
|
67 | ## The ProjectEditor function
|
68 |
|
69 | In the first example above, the editProject function is from Project to Promise<Project>. Project Editor functions can be more detailed.
|
70 |
|
71 | The signature of the `ProjectEditor` is as follows:
|
72 |
|
73 | ```typescript
|
74 | export type ProjectEditor<P = undefined, ER extends EditResult = EditResult> =
|
75 | (p: Project, context: HandlerContext, params?: P) => Promise<ER>;
|
76 | ```
|
77 | The parameter of type `Project` may be mutated by invocation of the editor function. Projects, like real world file systems, are mutable.
|
78 |
|
79 | `ProjectEditor` functions can be reused.
|