JuliaCI / PkgTemplates.jl

Create new Julia packages, the easy way
https://juliaci.github.io/PkgTemplates.jl
MIT License
636 stars 101 forks source link

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

Open nickrobinson251 opened 4 years ago

nickrobinson251 commented 4 years ago

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:
      - coyote@acme.corp
    on_success: never
    on_failure: always
    if: type = cron

(But again, TravisCI allows many options here).

Thinking out loud:

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

nickrobinson251 commented 4 years ago

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

@plugin struct Notify <: Plugin
    email::String = "me@acme.corp"
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?

christopher-dG commented 4 years ago

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" => "foo@bar.baz")

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.