Skip to content

PROTOTYPE: Add support for templated campaign specs

Warren Gifford requested to merge mrnugget/templated-specs into main

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

image

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:

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 (like previous_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

Merge request reports

Loading