PROTOTYPE: Add support for templated campaign specs
Created by: mrnugget
NOTE FOR REVIEWERS: This is a prototype and should be treated as such, which means: let's review idea/design/feasibility instead of concrete implementation details (but if you do have concrete feedback on the implementation, feel free to leave it as such).
This is a prototype to add templating to the steps
definitions in a campaign spec YAML file.
It's similar to the templating allowed in GitHub Actions.
Here is an excerpt from a campaign spec that uses templating. It runs comby only over the search results found in the repository by the repositoriesMatchingQuery
(that's the ${{ .Repository.SearchResultPaths }}
in the spec) and then runs goimports
only over the files modified by comby (the ${{ .PreviousStep.ModifiedFiles }}
):
name: templated-campaign
description: Use templates
on:
- repositoriesMatchingQuery: lang:go fmt.Sprintf("%d", :[v]) patterntype:structural -file:vendor count:10
steps:
- run: comby -in-place 'fmt.Sprintf("%d", :[v])' 'strconv.Itoa(:[v])' ${{ .Repository.SearchResultPaths }}
container: comby/comby
- run: goimports -w ${{ .PreviousStep.ModifiedFiles }}
container: unibeautify/goimports
changesetTemplate:
# [... changesetTemplate is unchanged ...]
Screenshot
Details
This is a tested prototype that works. Executing campaigns like this is much faster because comby only has to look at and touch the files it needs to modify, same goes for goimports.
What else is available in the templates? This is the definition of StepContext
, which is passed into the step.run
string before executing a step.
That means a user can access:
${{ .Repository.SearchResultPaths }}
-
${{ .Repository.Name }}
and the other fields and methods on*graphql.Repository
${{ .PreviousStep.ModifiedFiles }}
${{ .PreviousStep.AddedFiles }}
${{ .PreviousStep.DeletedFiles }}
Drawbacks
- there are no shortened aliases available as variables (
${{ search_result_paths }}
for example). Why? Because I couldn't come up with a consistent naming scheme that allows us to have a hierarchy too (likeprevious_step.modified_files
etc.). That doesn't mean we shouldn't do it though, since I don't like the.Foobar
syntax of Go's templating system.- Edit: I managed to get lower_case names + field access working (see here), which means we could use that instead.
- it might not be clear to the user that they have access to file paths since they're defining
*repositories*MatchingQuery
in their campaign spec. There might be a better way to define this. - with a large number of files and search results the rendered commands might become very long and thus hard to debug