PkgTemplates.jl icon indicating copy to clipboard operation
PkgTemplates.jl copied to clipboard

Extend `TravisCI` plugin (and other CI plugins) to allow notifications

Open nickrobinson251 opened this issue 5 years ago • 2 comments
trafficstars

Currently, the travis.yml template and TravisCI plugin do not allow users to configure notifications: https://github.com/invenia/PkgTemplates.jl/blob/5cf93cc4d8ed5b0b6887982046066fec238774c2/templates/travis.yml#L3-L4

The TravisCI plugin currently allows for quite a bit of configuration, however all setting are currently controlled either via (1) a Bool or (2) in the case of extra_versions a simple Vector of versions numbers. In contrast, TravisCI notifications allow for a lot of customisation, so it's not obvious how to set this up via the TravisCI plugin.

To be concrete, here's an example of what i'd like to be set for new packages created from a Template:

notifications:
  email:
    recipients:
      - [email protected]
    on_success: never
    on_failure: always
    if: type = cron

(But again, TravisCI allows many options here).

Thinking out loud:

  • i wonder if there's a way to have a notifcations field, whether that should take some kind of Notification struct, and whether such a struct should work with different CI plugins (e.g. i think GithubActions also supports email notifications).
  • Alternatively I wonder whether this is better handled via e.g. a separate plugin the has a custom hook method which edits the travis.yml, like how the Tests plugin adds extra content to the Project.toml file. Although i wonder how to do that given the current travis.yml template file sets notifications already; i suppose it'd have to come with a new travis.yml that removes the notifications bit from the current template.
  • Another option is a "half-way" between the above two: have a Bool that points to some other Notification plugin, analogous to how coverage works, e.g.
    - notifcations::Bool: Whether or not to send notifications. 
      Another notification plugin such as `SomeCustomNotification` must also be included.
    
    That said, the template file logic and Notification plugin(s) will still need to be more complex than is the case for e.g. CodeCov.
  • Yet another option is just to have a simple travis.yml template file for my particular use case e.g. that has a bit like:
      recipients: 
        {{#RECIPIENTS}}
        - {{{.}}}
        {{/RECIPIENTS}}
    
    Although come to think of it i'm not sure how to do this... Perhaps a custom plugin the wraps a TravisCI but also has a recipients::Vector{String} field?

I'm leaning towards the second option above for my use-case, but i do wonder about the general case.

nickrobinson251 avatar Aug 31 '20 12:08 nickrobinson251

Here's what i went with for my use-case

@plugin struct Notify <: Plugin
    email::String = "[email protected]"
end

# `priority` should be lower than `TravisCI`, so that `Notify` runs after `TravisCI`.
const PRIORITY = PkgTemplates.priority(TravisCI(), PkgTemplates.hook) - 1000
PkgTemplates.priority(::Notify, ::Function) = PRIORITY

function PkgTemplates.validate(notify::Notify, t::Template)
    has_travis = any(p -> p isa TravisCI, t.plugins)
    has_travis || @warn "No `TravisCI` plugin. `Notify` plugin will have no effect."
    return nothing
end

function PkgTemplates.hook(notify::Notify, t::Template, pkg_dir::AbstractString)
    add_notifications(notify, pkg_dir)
    return nothing
end

function add_notifications(notify::Notify, pkg_dir)
    travis_file = joinpath(pkg_dir, ".travis.yml")
    isfile(travis_file) || @warn "No `.travis.yml` file found" travis_file
    if contains(read(travis_file, String), "notifications")
        @warn "Notification section already in `.travis.yml`. File may now be invalid."
    end
    notifications = """
    notifications:
      email:
        recipients:
          - $(notify.email)
        on_success: never
        on_failure: always
        if: type = cron
    """
    open(travis_file, "a") do travis
        write(travis, notifications)
    end
    return nothing
end

plus a travis.yml file that doesn't contain notifications

This makes me think: is

 notifications: 
   email: false 

the same as not having a notifications section?

If so, can we just remove that from the template file?

nickrobinson251 avatar Aug 31 '20 17:08 nickrobinson251

IIRC if you don't put a notifications section, emails are sent by default to the repo owner (not sure what happens for orgs) and it's really annoying.

Your approach definitely works, but the last option might be simplest. You can do it with user_view.

So your custom template file:

language: julia
#
# everything from the default file goes here except notifications
#
notifications:
  email:
    recipients:
      - {{{EMAIL}}}
  # etc

And a bit of code to write:

PkgTemplates.user_view(::TravisCI, ::Template, ::AbstractString) = Dict("EMAIL" => "[email protected]")

Currently there's no way to get a "dynamic" email that depends on any runtime value in the Travis plugin or the Template... I've thought about adding some kind of meta::Dict{Symbol, Any} field to each plugin to make the user_view workflow more useful.

christopher-dG avatar Sep 01 '20 15:09 christopher-dG