PkgTemplates.jl
PkgTemplates.jl copied to clipboard
Extend `TravisCI` plugin (and other CI plugins) to allow notifications
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
notifcationsfield, whether that should take some kind ofNotificationstruct, 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
hookmethod which edits thetravis.yml, like how theTestsplugin adds extra content to theProject.tomlfile. Although i wonder how to do that given the currenttravis.ymltemplate file setsnotificationsalready; i suppose it'd have to come with a newtravis.ymlthat removes thenotificationsbit from the current template. - Another option is a "half-way" between the above two: have a
Boolthat points to some otherNotificationplugin, analogous to howcoverageworks, e.g.
That said, the template file logic and- notifcations::Bool: Whether or not to send notifications. Another notification plugin such as `SomeCustomNotification` must also be included.Notificationplugin(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.ymltemplate file for my particular use case e.g. that has a bit like:
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 arecipients: {{#RECIPIENTS}} - {{{.}}} {{/RECIPIENTS}}recipients::Vector{String}field?
I'm leaning towards the second option above for my use-case, but i do wonder about the general case.
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?
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.