Rework code, fix/add tests, fix/add docs. All the things.

This commit is contained in:
Chris de Graaf 2017-08-17 17:06:05 -05:00
parent dfa9f123de
commit d009acf24b
20 changed files with 479 additions and 342 deletions

View File

@ -33,5 +33,6 @@ build_script:
test_script: test_script:
- C:\projects\julia\bin\julia -e "Pkg.test(\"PkgTemplates\")" - C:\projects\julia\bin\julia -e "Pkg.test(\"PkgTemplates\")"
after_script: after_script:
- C:\projects\julia\bin\julia -e "cd(Pkg.dir(\"AppVeyorTesting\")); Pkg.add(\"Coverage\"); using Coverage; Codecov.submit(process_folder())" - C:\projects\julia\bin\julia -e "cd(Pkg.dir(\"AppVeyorTesting\")); Pkg.add(\"Coverage\"); using Coverage; Codecov.submit(process_folder())"

2
.gitignore vendored
View File

@ -1,8 +1,6 @@
.DS_Store .DS_Store
# CodeCov generated files
*.jl.cov *.jl.cov
*.jl.*.cov *.jl.*.cov
*.jl.mem *.jl.mem
# Documenter generated files
/docs/build/ /docs/build/
/docs/site/ /docs/site/

View File

@ -12,8 +12,6 @@ script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("PkgTemplates"); Pkg.test("PkgTemplates"; coverage=true)' - julia -e 'Pkg.clone(pwd()); Pkg.build("PkgTemplates"); Pkg.test("PkgTemplates"; coverage=true)'
after_success: after_success:
# push coverage results to CodeCov
- julia -e 'cd(Pkg.dir("PkgTemplates")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())' - julia -e 'cd(Pkg.dir("PkgTemplates")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'
# build documentation
- julia -e 'Pkg.add("Documenter")' - julia -e 'Pkg.add("Documenter")'
- julia -e 'cd(Pkg.dir("PkgTemplates")); include(joinpath("docs", "make.jl"))' - julia -e 'cd(Pkg.dir("PkgTemplates")); include(joinpath("docs", "make.jl"))'

View File

@ -1,193 +0,0 @@
# Contributing to PkgTemplates
The best way to contribute to `PkgTemplates` is by adding new plugins.
There are two main types of plugins:
[`GenericPlugin`](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugins.html#GenericPlugin-1)s
and
[`CustomPlugin`](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugins.html#CustomPlugin-1)s.
## Writing a Generic Plugin
As the name suggests, generic plugins are simpler than custom ones, and as
such are extremely easy to implement. They have the ability to add patterns
the the generated `.gitignore`, as well as create a single configuration file.
We're going to define a new generic plugin `MyPlugin` in
`src/plugins/myplugin.jl`:
```julia
@auto_hash_equals struct MyPlugin <: GenericPlugin
gitignore::Vector{AbstractString}
src::Nullable{AbstractString}
dest::AbstractString
badges::Vector{AbstractString}
view::Dict{String, Any}
function MyPlugin(; config_file::Union{AbstractString, Void}="")
if config_file != nothing
if isempty(config_file)
config_file = joinpath(DEFAULTS_DIR, "myplugin.yml")
elseif !isfile(config_file)
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
end
end
new([], config_file, ".myplugin.yml", [], Dict{String, Any}())
end
end
```
That's all there is to it! Let's take a better look at what we've done:
* The plugin has five attributes, these must be exactly as they are.
* `gitignore` is the array of patterns to add the the generated package's
`.gitignore`, we chose not to add any with this plugin.
* `src` is the location of the config file we're going to copy into the
generated package repository. If this is `nothing`, no config file will be
generated. This came from the `config_file` keyword argument, which
defaulted to an empty string. That's because we've placed a default
config file at `defaults/myplugin.yml`.
* `dest` is the path to our generated config file, relative to the root of
the package repository. In this example, the file will go in
`.myplugin.yml` at the root of the repository.
* `badges` is an array of Markdown-formatted badge strings to be displayed
on the package's README. We chose not to include any here. TODO talk about
`substitute`.
* `view` is a dictionary of additional replacements to `substitute`.
Plenty of services like
[`TravisCI`](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugins.html#TravisCI-1)
and
[`CodeCov`](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugins.html#CodeCov-1)
follow this format, so generic plugins should be able to get you pretty far.
## Writing a Custom Plugin
When a service doesn't follow the pattern demonstrated above, it's time to write a custom
plugin. These are still pretty simple, needing at most two additional methods. Let's create
a custom plugin called `Gamble` in `src/plugins/gamble.jl` that only generates a file if
you get lucky enough:
```julia
@auto_hash_equals struct Gamble <: CustomPlugin
gitignore:Vector{AbstractString}
src::AbstractString
success::Bool
function Gamble(config_file::AbstractString)
if !isfile(config_file)
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
end
success = rand() > 0.8
println(success ? "Congratulations!" : "Maybe next time.")
new([], config_file, success)
end
end
function badges(plugin: Gamble, user::AbstractString, pkg_name::AbstractString)
if plugin.success
return ["[![You won!](https://i.imgur.com/poker-chip)](https://pokerstars.net)"]
else
return String[]
end
end
function gen_plugin(plugin::Gamble, template::Template, pkg_name::AbstractString)
if plugin.success
text = substitute(readstring(plugin.src), template, pkg_name)
gen_file(joinpath(t.temp_dir, ".gambler.yml"), text)
return [".gambler.yml"]
else
return String[]
end
end
```
With that, we've got everything we need. Note that this plugin still has a `gitignore`
attribute; it's required for all plugins. Let's look at the extra methods we implemented:
#### `gen_plugin`
We read the text from the plugin's source file, and then we run it through the `substitute`
function (more on that [later](#template-substitution)).
Next, we use `gen_file` to write the text, with substitutions applied, to the destination
file in `t.temp_dir`. Generating our repository in a temp directory means we're not stuck
with leftovers in the case of an error.
This function returns an array of all the root-level files or directories
that were created. If both `foo/bar` and `foo/baz` were created, we only need
to return `["foo/"]`.
#### `badges`
This function returns an array of Markdown-formatted badges to be displayed on
the package README. You can find badges and Markdown strings for just about
everything on [Shields.io](https://shields.io).
This will do the trick, but if we want our badge to appear at a specific
position in the README, we need to edit `BADGE_ORDER` in
[`src/PkgTemplates.jl`(https://github.com/invenia/PkgTemplates.jl/blob/master/src/PkgTemplates.jl).
Say we want our badge to appear before all others, we'll add `Gamble` to the
beginning of the array.
That's all there is to it! We've just created a nifty custom plugin.
***
### Template Substitution
Since plugin configuration files are often specific to the package they belong
to, we might want to replace some placeholder values in our plugin's config
file. We can do this by following
[Mustache.jl](https://github.com/jverzani/Mustache.jl)'s rules. Some
replacements are defined by `PkgTemplates`:
* `{{PKGNAME}}` is replaced by `pkg_name`.
* `{{VERSION}}` is replaced by `$major.$minor` corresponding to
`template.julia_version`.
Some conditional replacements are also defined:
* `{{DOCUMENTER}}Documenter{{/DOCUMENTER}}`
* "Documenter" only appears in the rendered text if the template contains
a [`Documenter`](src/plugins/documenter.jl) subtype.
* `{{CODECOV}}CodeCov{{/CODECOV}}`
* "CodeCov" only appears in the rendered text if the template contains
the [`CodeCov`](src/plugins/codecov.jl) plugin.
* `{{#AFTER}}After{{/AFTER}}`
* "After" only appears in the rendered text if something needs to happen
**after** CI testing occurs. As of right now, this is true when either of
the above two conditions are true.
We can also specify our own replacements by passing a dictionary to
`substitute`:
```julia
view = Dict("KEY" => "VAL", "HEADS" => 2rand() > 1)
text = """
{{KEY}}
{{PKGNAME}}
{{#HEADS}}Heads{{/HEADS}}
"""
substituted = substitute(text, "MyPkg", template; view=view)
```
This will return `"VAL\nMyPkg\nHeads\n"` if `2rand() > 1` was true,
`"VAL\nMyPkg\n\n"` otherwise.
Note the double newline in the second outcome; `Mustache` has a bug with
conditionals that inserts extra newlines (more detail
[here](https://github.com/jverzani/Mustache.jl/issues/47)). We can get around
this by writing ugly template files, like so:
```
{{KEY}}
{{PKGNAME}}{{#HEADS}}
Heads{{/HEADS}}
```
The resulting string will end with a single newline regardless of the value
of `view["HEADS"]`
Also note that conditionals without a corresponding key in `view` won't error,
but will simply be evaluated as false.

View File

@ -85,5 +85,11 @@ Information on each keyword as well as plugin types can be found in the
`PkgTemplates` is similar in functionality to `PkgDev`'s `generate` function. `PkgTemplates` is similar in functionality to `PkgDev`'s `generate` function.
However, `PkgTemplates` offers more customizability in templates and more However, `PkgTemplates` offers more customizability in templates and more
extensibility via plugins. For the package registration and release management extensibility via plugins. For the package registration and release management
features that `PkgTemplates` lacks, you are encouraged to use features that `PkgTemplates` doesn't include, you are encouraged to use
[AttoBot](https://github.com/apps/attobot) instead. [AttoBot](https://github.com/apps/attobot) instead.
## Contributing
It's extremely easy to extend `PkgTemplates` with new plugins. To get started,
check out the
[plugin development guide](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugin_development.html).

View File

@ -32,6 +32,8 @@ build_script:
Pkg.clone(pwd(), \"{{PKGNAME}}\"); Pkg.build(\"{{PKGNAME}}\")" Pkg.clone(pwd(), \"{{PKGNAME}}\"); Pkg.build(\"{{PKGNAME}}\")"
test_script: test_script:
- C:\projects\julia\bin\julia -e "Pkg.test(\"{{PKGNAME}}\")" - C:\projects\julia\bin\julia -e "Pkg.test(\"{{PKGNAME}}\")"{{#AFTER}}
{{#AFTER}}after_script:
{{#CODECOV}}- C:\projects\julia\bin\julia -e "cd(Pkg.dir(\"{{PKGNAME}}\")); Pkg.add(\"Coverage\"); using Coverage; Codecov.submit(process_folder())"{{/CODECOV}}{{/AFTER}} after_script:{{#CODECOV}}
- C:\projects\julia\bin\julia -e "cd(Pkg.dir(\"{{PKGNAME}}\")); Pkg.add(\"Coverage\"); using Coverage; Codecov.submit(process_folder())"{{/CODECOV}}{{#COVERALLS}}
- C:\projects\julia\bin\julia -e "cd(Pkg.dir(\"{{PKGNAME}}\")); Pkg.add(\"Coverage\"); using Coverage; Coveralls.submit(process_folder())"{{/COVERALLS}}{{/AFTER}}

View File

@ -10,8 +10,9 @@ notifications:
email: false email: false
script: script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("{{PKGNAME}}"); Pkg.test("{{PKGNAME}}"; coverage=true)' - julia -e 'Pkg.clone(pwd()); Pkg.build("{{PKGNAME}}"); Pkg.test("{{PKGNAME}}"; coverage=true)'{{#AFTER}}
{{#AFTER}}after_success: after_success:{{#CODECOV}}
{{#CODECOV}}- julia -e 'cd(Pkg.dir("{{PKGNAME}}")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'{{/CODECOV}} - julia -e 'cd(Pkg.dir("{{PKGNAME}}")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'{{/CODECOV}}{{#COVERALLS}}
{{#DOCUMENTER}}- julia -e 'Pkg.add("Documenter")' - julia -e 'cd(Pkg.dir("{{PKGNAME}}")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder())'{{/COVERALLS}}{{#DOCUMENTER}}
- julia -e 'Pkg.add("Documenter")'
- julia -e 'cd(Pkg.dir("{{PKGNAME}}")); include(joinpath("docs", "make.jl"))'{{/DOCUMENTER}}{{/AFTER}} - julia -e 'cd(Pkg.dir("{{PKGNAME}}")); include(joinpath("docs", "make.jl"))'{{/DOCUMENTER}}{{/AFTER}}

View File

@ -7,6 +7,7 @@ makedocs(
"Home" => "index.md", "Home" => "index.md",
"Package Generation" => "pages/package_generation.md", "Package Generation" => "pages/package_generation.md",
"Plugins" => "pages/plugins.md", "Plugins" => "pages/plugins.md",
"Plugin Development" => "pages/plugin_development.md",
"Licenses" => "pages/licenses.md", "Licenses" => "pages/licenses.md",
"Index" => "pages/index.md" "Index" => "pages/index.md"
], ],

View File

@ -0,0 +1,62 @@
```@meta
CurrentModule = PkgTemplates
```
# Plugin Development
The best and easiest way to contribute to `PkgTemplates` is to write new
plugins.
There are two types of plugins: [`GenericPlugin`](@ref)s and [`CustomPlugin`](@ref)s.
## Generic Plugins
```@docs
GenericPlugin
```
## Custom Plugins
```@docs
CustomPlugin
```
### CustomPlugin required methods
#### `gen_plugin`
```@docs
gen_plugin
```
#### `badges`
```@docs
badges
```
## Helper Functions
#### gen_file
```@docs
gen_file
```
#### substitute
```@docs
substitute
```
#### badge
```@docs
badge
```
#### version_floor
```@docs
version_floor
```

View File

@ -4,8 +4,9 @@ CurrentModule = PkgTemplates
# Plugins # Plugins
For information on writing your own plugins, see Plugins are the driver for `PkgTemplates`'s customization and extension. This page
[CONTRIBUTING.md](https://github.com/invenia/PkgTemplates.jl/tree/master/CONTRIBUTING.md). describes plugins that already exist; for information on writing your own plugins, see the
[plugin development guide](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugin_development.html).
## TravisCI ## TravisCI
@ -25,6 +26,12 @@ AppVeyor
CodeCov CodeCov
``` ```
## Coveralls
```@docs
Coveralls
```
## Documenter ## Documenter
```@docs ```@docs

View File

@ -42,8 +42,11 @@ function generate(
end end
LibGit2.commit(repo, "Empty initial commit") LibGit2.commit(repo, "Empty initial commit")
info("Made initial empty commit") info("Made initial empty commit")
rmt = ssh ? "git@$(t.host):$(t.user)/$pkg_name.jl.git" : rmt = if ssh
"git@$(t.host):$(t.user)/$pkg_name.jl.git"
else
"https://$(t.host)/$(t.user)/$pkg_name.jl" "https://$(t.host)/$(t.user)/$pkg_name.jl"
end
LibGit2.set_remote_url(repo, rmt) LibGit2.set_remote_url(repo, rmt)
info("Set remote origin to $rmt") info("Set remote origin to $rmt")
@ -72,7 +75,7 @@ function generate(
info("Committed files generated by PkgTemplates") info("Committed files generated by PkgTemplates")
multiple_branches = length(collect(LibGit2.GitBranchIter(repo))) > 1 multiple_branches = length(collect(LibGit2.GitBranchIter(repo))) > 1
info("Copying temporary package directory into $(t.dir)/") info("Copying temporary package directory into $(t.dir)/")
cp(temp_pkg_dir, pkg_dir; remove_destination=force) mv(temp_pkg_dir, pkg_dir; remove_destination=force)
rm(t.temp_dir; recursive=true) rm(t.temp_dir; recursive=true)
info("Finished") info("Finished")
if multiple_branches if multiple_branches
@ -103,7 +106,7 @@ function gen_readme(pkg_name::AbstractString, template::Template)
badges(template.plugins[plugin_type], template.user, pkg_name), badges(template.plugins[plugin_type], template.user, pkg_name),
"\n", "\n",
) )
deleteat!(remaining, findin(remaining, plugin_type)) deleteat!(remaining, find(p -> p == plugin_type, remaining)[1])
end end
end end
for plugin_type in remaining for plugin_type in remaining
@ -273,71 +276,69 @@ function version_floor(v::VersionNumber=VERSION)
end end
end end
"""
substitute(template::AbstractString, view::Dict{String, Any}) -> String
Replace placeholders in a template string. The input string is not modified.
# Arguments
* `template::AbstracString`: Template string in which to make replacements.
* `view::Dict{String, Any}`: (Placeholder => value) pairs.
Returns the template string with replacements applied.
# Notes
Due to a bug in `Mustache`, conditionals often insert undesired newlines (more detail
[here](https://github.com/jverzani/Mustache.jl/issues/47)).
For example:
```
A
{{#B}}B{{/B}}
C
```
When `view` doesn't have a `"B"` key (or it does, but it's false), this becomes
`"A\\n\\nC"` We can get around this by writing ugly template files, like so:
```
A{{#B}}
B{{/B}}
C
```
In this case, the result is `"A\\nB\\nC"`, like we want it to be.
Also note that conditionals without a corresponding key in `view` won't error,
but will simply be evaluated as false.
"""
substitute(template::AbstractString, view::Dict{String, Any}) = render(template, view)
""" """
substitute( substitute(
template::AbstractString, template::AbstractString,
pkg_template::Template; pkg_template::Template;
pkg_name::AbstractString,
view::Dict{String, Any}=Dict{String, Any}(), view::Dict{String, Any}=Dict{String, Any}(),
) -> String ) -> String
Replace placeholders in `template`. The input string is not modified. Replace placeholders in template string, using some default replacements based on the
package template. The input string is not modified.
# Arguments:
* `template::AbstractString`: Template string to make replacements in.
* `pkg_template::Template`: The package template in use.
* `pkg_name::AbstractString`: Name of the package being created.
* `view::Dict{String, Any}=Dict{String, Any}()`: Additional values to be substituted.
Returns the text with substitutions applied.
""" """
function substitute( function substitute(
template::AbstractString, template::AbstractString,
pkg_template::Template, pkg_template::Template;
pkg_name::AbstractString;
view::Dict{String, Any}=Dict{String, Any}(), view::Dict{String, Any}=Dict{String, Any}(),
) )
d = merge!(Dict{String, Any}(), view)
d["PKGNAME"] = pkg_name
d["USER"] = pkg_template.user
v = pkg_template.julia_version
# Don't use version_floor here because we don't want the trailing '-' on prereleases. # Don't use version_floor here because we don't want the trailing '-' on prereleases.
d["VERSION"] = "$(v.major).$(v.minor)" v = pkg_template.julia_version
d = Dict{String, Any}(
"USER" => pkg_template.user,
"VERSION" => "$(v.major).$(v.minor)",
"DOCUMENTER" => any(isa(p, Documenter) for p in values(pkg_template.plugins)),
"CODECOV" => haskey(pkg_template.plugins, CodeCov),
"COVERALLS" => haskey(pkg_template.plugins, Coveralls),
)
# d["AFTER"] is true whenever something needs to occur in a CI "after_script". # d["AFTER"] is true whenever something needs to occur in a CI "after_script".
if any(isa(p, Documenter) for p in values(pkg_template.plugins)) d["AFTER"] = d["DOCUMENTER"] || d["CODECOV"] || d["COVERALLS"]
d["DOCUMENTER"] = true return substitute(template, merge(d, view))
d["AFTER"] = true
end
if haskey(pkg_template.plugins, CodeCov)
d["CODECOV"] = true
d["AFTER"] = true
end
return render(template, d)
end
"""
substitute(
template::AbstractString,
pkg_plugin::Plugin;
pkg_name::AbstractString,
view::Dict{String, Any}=Dict{String, Any}(),
) -> String
Replace placeholders in `template`. The input string is not modified.
# Arguments:
* `template::AbstractString`: Template string to make replacements in.
* `pkg_plugin::Plugin`: The plugin in use.
* `pkg_name::AbstractString`: Name of the package being created.
* `view::Dict{String, Any}=Dict{String, Any}()`: Additional values to be substituted.
Returns the text with substitutions applied.
"""
function substitute(
template::AbstractString,
pkg_plugin::Plugin,
pkg_name::AbstractString;
view::Dict{String, Any}=Dict{String, Any}(),
)
return render(template, merge(Dict("PKGNAME" => pkg_name), view))
end end

View File

@ -1,28 +1,123 @@
abstract type GenericPlugin <: Plugin end
abstract type CustomPlugin <: Plugin end
""" """
badges(\_::Plugin, user::AbstractString, pkg_name::AbstractString) Generic plugins are plugins that add any number of patterns to the generated package's
`.gitignore`, and have at most one associated file to generate.
Generate Markdown badges for the current package. # Attributes
* `gitignore::Vector{AbstractString}`: Array of patterns to be added to the `.gitignore` of
generated packages that use this plugin.
* `src::Nullable{AbstractString}`: Path to the file that will be copied into the generated
package repository. If set to `nothing`, no file will be generated. When this defaults
to an empty string, there should be a default file in `defaults` that will be copied.
* `dest::AbstractString`: Path to the generated file, relative to the root of the generated
package repository.
* `badges::Vector{Vector{AbstractString}}`: Array of arrays containing information to
create a Markdown-formatted badge from the plugin. Each entry is of the form
`[hover_text, image_url, link_url]`. Entries will be run through [`substitute`](@ref),
so they may contain placeholder values.
* `view::Dict{String, Any}`: Additional substitutions to make in both the plugin's badges
and its associated file. See [`substitute`](@ref) for details.
# Arguments # Example
* `plugin::Plugin`: Plugin whose badges we are generating. ```julia
* `user::AbstractString`: Username of the package creator. @auto_hash_equals struct MyPlugin <: GenericPlugin
* `pkg_name::AbstractString`: Name of the package. gitignore::Vector{AbstractString}
src::Nullable{AbstractString}
dest::AbstractString
badges::Vector{Vector{AbstractString}}
view::Dict{String, Any}
Returns an array of Markdown badges. function MyPlugin(; config_file::Union{AbstractString, Void}="")
""" if config_file != nothing
badges(plugin::Plugin, user::AbstractString, pkg_name::AbstractString) = String[] if isempty(config_file)
config_file = joinpath(DEFAULTS_DIR, "myplugin.yml")
function badges(plugin::GenericPlugin, user::AbstractString, pkg_name::AbstractString) elseif !isfile(config_file)
return substitute.( throw(ArgumentError(
plugin.badges, "File \$(abspath(config_file)) does not exist"
plugin, ))
pkg_name; end
view=Dict{String, Any}("USER" => user) end
) new(
["*.mgp"],
config_file,
".mypugin.yml",
[
[
"My Plugin",
"https://myplugin.com/badge-{{YEAR}}.png",
"https://myplugin.com/{{USER}}/{{PKGNAME}}.jl",
],
],
Dict{String, Any}("YEAR" => Dates.year(Dates.now())),
)
end
end end
```
The above plugin ignores files ending with `.mgp`, copies `defaults/myplugin.yml` by
default, and creates a badge that links to the project on its own site, using the default
substitutions with one addition: `{{YEAR}} => Dates.year(Dates.now())`.
"""
abstract type GenericPlugin <: Plugin end
"""
Custom plugins are plugins whose behaviour does not follow the [`GenericPlugin`](@ref)
pattern. They can implement [`gen_plugin`](@ref) and [`badges`](@ref) in any way they
choose.
# Attributes
* `gitignore::Vector{AbstractString}`: Array of patterns to be added to the `.gitignore` of
generated packages that use this plugin.
# Example
```julia
@auto_hash_equals struct MyPlugin <: CustomPlugin
gitignore::Vector{AbstractString}
lucky::Bool
MyPlugin() = new([], rand() > 0.8)
function gen_plugin(
plugin::MyPlugin,
template::Template,
pkg_name::AbstractString
)
if plugin.lucky
text = substitute(
"You got lucky with {{PKGNAME}}, {{USER}}!"),
template,
)
gen_file(joinpath(template.temp_dir, ".myplugin.yml"), text)
else
println("Maybe next time.")
end
end
function badges(
plugin::MyPlugin,
user::AbstractString,
pkg_name::AbstractString,
)
if plugin.lucky
return [
badge(
"You got lucky!",
"https://myplugin.com/badge.png",
"https://myplugin.com/\$user/\$pkg_name.jl",
),
]
else
return String[]
end
end
end
```
This plugin doesn't do much, but it demonstrates how [`gen_plugin`](@ref) and
[`badges`](@ref) can be implemented using [`substitute`](@ref), [`gen_file`](@ref),
and [`badge`](@ref).
"""
abstract type CustomPlugin <: Plugin end
""" """
gen_plugin(plugin::Plugin, template::Template, pkg_name::AbstractString) -> Vector{String} gen_plugin(plugin::Plugin, template::Template, pkg_name::AbstractString) -> Vector{String}
@ -39,16 +134,50 @@ Returns an array of generated file/directory names.
gen_plugin(plugin::Plugin, template::Template, pkg_name::AbstractString) = String[] gen_plugin(plugin::Plugin, template::Template, pkg_name::AbstractString) = String[]
function gen_plugin(plugin::GenericPlugin, template::Template, pkg_name::AbstractString) function gen_plugin(plugin::GenericPlugin, template::Template, pkg_name::AbstractString)
try src = try
text = substitute( get(plugin.src)
readstring(get(plugin.src)),
template,
pkg_name;
view=plugin.view,
)
gen_file(joinpath(template.temp_dir, pkg_name, plugin.dest), text)
return [plugin.dest]
catch catch
return String[] return String[]
end end
text = substitute(
readstring(src),
template;
view=merge(Dict("PKGNAME" => pkg_name), plugin.view),
)
gen_file(joinpath(template.temp_dir, pkg_name, plugin.dest), text)
return [plugin.dest]
end
"""
badges(plugin::Plugin, user::AbstractString, pkg_name::AbstractString) -> Vector{String}
Generate Markdown badges for the plugin.
# Arguments
* `plugin::Plugin`: Plugin whose badges we are generating.
* `user::AbstractString`: Username of the package creator.
* `pkg_name::AbstractString`: Name of the package.
Returns an array of Markdown badges.
"""
badges(plugin::Plugin, user::AbstractString, pkg_name::AbstractString) = String[]
function badges(plugin::GenericPlugin, user::AbstractString, pkg_name::AbstractString)
# Give higher priority to replacements defined in the plugin's view.
view = merge(Dict("USER" => user, "PKGNAME" => pkg_name), plugin.view)
return [badge([substitute(part, view) for part in b]...) for b in plugin.badges]
end
"""
badge(hover::AbstractString, image::AbstractString, image::AbstractString) -> String
Format a single Markdown badge.
# Arguments
* `hover::AbstractString`: Text to appear when the mouse is hovered over the badge.
* `image::AbstractString`: URL to the image to display.
* `link::AbstractString`: URL to go to upon clicking the badge.
"""
function badge(hover::AbstractString, image::AbstractString, link::AbstractString)
return "[![$hover]($image)]($link)"
end end

View File

@ -1,7 +1,8 @@
""" """
AppVeyor(; config_file::Union{AbstractString, Void}="") -> GenericPlugin AppVeyor(; config_file::Union{AbstractString, Void}="") -> GenericPlugin
Add AppVeyor to a template's plugins to add AppVeyor CI support. Add `AppVeyor` to a template's plugins to add a `.appveyor.yml` configuration file to
generated repositories, and an appropriate badge to the README.
# Keyword Arguments # Keyword Arguments
* `config_file::Union{AbstractString, Void}=""`: Path to a custom `.appveyor.yml`. * `config_file::Union{AbstractString, Void}=""`: Path to a custom `.appveyor.yml`.
@ -11,7 +12,7 @@ Add AppVeyor to a template's plugins to add AppVeyor CI support.
gitignore::Vector{AbstractString} gitignore::Vector{AbstractString}
src::Nullable{AbstractString} src::Nullable{AbstractString}
dest::AbstractString dest::AbstractString
badges::Vector{AbstractString} badges::Vector{Vector{AbstractString}}
view::Dict{String, Any} view::Dict{String, Any}
function AppVeyor(; config_file::Union{AbstractString, Void}="") function AppVeyor(; config_file::Union{AbstractString, Void}="")
@ -26,7 +27,13 @@ Add AppVeyor to a template's plugins to add AppVeyor CI support.
[], [],
config_file, config_file,
".appveyor.yml", ".appveyor.yml",
["[![Build Status](https://ci.appveyor.com/api/projects/status/github/{{USER}}/{{PKGNAME}}.jl?svg=true)](https://ci.appveyor.com/project/{{USER}}/{{PKGNAME}}-jl)"], [
[
"Build Status",
"https://ci.appveyor.com/api/projects/status/github/{{USER}}/{{PKGNAME}}.jl?svg=true",
"https://ci.appveyor.com/project/{{USER}}/{{PKGNAME}}-jl",
],
],
Dict{String, Any}(), Dict{String, Any}(),
) )
end end

View File

@ -1,7 +1,9 @@
""" """
CodeCov(; config_file::Union{AbstractString, Void}="") -> GenericPlugin CodeCov(; config_file::Union{AbstractString, Void}="") -> GenericPlugin
Add CodeCov to a template's plugins to enable CodeCov coverage reports. Add `CodeCov` to a template's plugins to add a `.codecov.yml` configuration file to
generated repositories, and an appropriate badge to the README. Also updates the
`.gitignore` accordingly.
# Keyword Arguments: # Keyword Arguments:
* `config_file::Union{AbstractString, Void}=""`: Path to a custom `.codecov.yml`. * `config_file::Union{AbstractString, Void}=""`: Path to a custom `.codecov.yml`.
@ -11,7 +13,7 @@ Add CodeCov to a template's plugins to enable CodeCov coverage reports.
gitignore::Vector{AbstractString} gitignore::Vector{AbstractString}
src::Nullable{AbstractString} src::Nullable{AbstractString}
dest::AbstractString dest::AbstractString
badges::Vector{AbstractString} badges::Vector{Vector{AbstractString}}
view::Dict{String, Any} view::Dict{String, Any}
function CodeCov(; config_file::Union{AbstractString, Void}="") function CodeCov(; config_file::Union{AbstractString, Void}="")
@ -26,7 +28,13 @@ Add CodeCov to a template's plugins to enable CodeCov coverage reports.
["*.jl.cov", "*.jl.*.cov", "*.jl.mem"], ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"],
config_file, config_file,
".codecov.yml", ".codecov.yml",
["[![CodeCov](https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl)"], [
[
"CodeCov",
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl/branch/master/graph/badge.svg",
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl",
],
],
Dict{String, Any}(), Dict{String, Any}(),
) )
end end

View File

@ -1,7 +1,9 @@
""" """
Coveralls(; config_file::Union{AbstractString, Void}="") -> Coveralls Coveralls(; config_file::Union{AbstractString, Void}="") -> Coveralls
Add Coveralls to a template's plugins to enable Coveralls coverage reports. Add `Coveralls` to a template's plugins to optionally add a `.coveralls.yml` configuration
file to generated repositories, and an appropriate badge to the README. Also updates the
`.gitignore` accordingly.
# Keyword Arguments: # Keyword Arguments:
* `config_file::Union{AbstractString, Void}=nothing`: Path to a custom `.coveralls.yml`. * `config_file::Union{AbstractString, Void}=nothing`: Path to a custom `.coveralls.yml`.
@ -11,7 +13,7 @@ Add Coveralls to a template's plugins to enable Coveralls coverage reports.
gitignore::Vector{AbstractString} gitignore::Vector{AbstractString}
src::Nullable{AbstractString} src::Nullable{AbstractString}
dest::AbstractString dest::AbstractString
badges::Vector{AbstractString} badges::Vector{Vector{AbstractString}}
view::Dict{String, Any} view::Dict{String, Any}
function Coveralls(; config_file::Union{AbstractString, Void}=nothing) function Coveralls(; config_file::Union{AbstractString, Void}=nothing)
@ -22,7 +24,13 @@ Add Coveralls to a template's plugins to enable Coveralls coverage reports.
["*.jl.cov", "*.jl.*.cov", "*.jl.mem"], ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"],
config_file, config_file,
".coveralls.yml", ".coveralls.yml",
["[![Coveralls](https://coveralls.io/repos/github/{{USER}}/{{PKGNAME}}.jl/badge.svg?branch=master)](https://coveralls.io/github/{{USER}}/{{PKGNAME}}.jl?branch=master)"], [
[
"Coveralls",
"https://coveralls.io/repos/github/{{USER}}/{{PKGNAME}}.jl/badge.svg?branch=master",
"https://coveralls.io/github/{{USER}}/{{PKGNAME}}.jl?branch=master",
],
],
Dict{String, Any}(), Dict{String, Any}(),
) )
end end

View File

@ -1,19 +1,9 @@
""" """
Add a Documenter subtype to a template's plugins to add support for Add a `Documenter` subtype to a template's plugins to add support for documentation
[Documenter.jl](https://github.com/JuliaDocs/Documenter.jl). generation via [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl).
""" """
abstract type Documenter <: CustomPlugin end abstract type Documenter <: CustomPlugin end
"""
gen_plugin(plugin::Documenter, template::Template, pkg_name::AbstractString) -> Void
Generate the "docs" directory with files common to all Documenter subtypes.
# Arguments
* `plugin::Documenter`: Plugin whose files are being generated.
* `template::Template`: Template configuration and plugins.
* `pkg_name::AbstractString`: Name of the package.
"""
function gen_plugin(plugin::Documenter, template::Template, pkg_name::AbstractString) function gen_plugin(plugin::Documenter, template::Template, pkg_name::AbstractString)
if Pkg.installed("Documenter") == nothing if Pkg.installed("Documenter") == nothing
info("Adding Documenter.jl") info("Adding Documenter.jl")

View File

@ -1,7 +1,9 @@
""" """
GitHubPages(; assets::Vector{AbstractString}=String[]) -> GitHubPages GitHubPages(; assets::Vector{AbstractString}=String[]) -> GitHubPages
Add GitHubPages to a template's plugins to add Documenter.jl support via GitHub Pages. Add `GitHubPages` to a template's plugins to add [Documenter](@ref) support via GitHub
Pages, including automatic uploading of documentation from [`TravisCI`](@ref). Also
adds appropriate badges to the README, and updates the `.gitignore` accordingly.
# Keyword Arguments # Keyword Arguments
* `assets::Vector{String}=String[]`: Array of paths to Documenter asset files. * `assets::Vector{String}=String[]`: Array of paths to Documenter asset files.
@ -23,8 +25,8 @@ end
function badges(_::GitHubPages, user::AbstractString, pkg_name::AbstractString) function badges(_::GitHubPages, user::AbstractString, pkg_name::AbstractString)
return [ return [
"[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://$user.github.io/$pkg_name.jl/stable)" badge("Stable", "https://img.shields.io/badge/docs-stable-blue.svg", "https://$user.github.io/$pkg_name.jl/stable")
"[![Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://$user.github.io/$pkg_name.jl/latest)" badge("Latest", "https://img.shields.io/badge/docs-latest-blue.svg", "https://$user.github.io/$pkg_name.jl/latest")
] ]
end end

View File

@ -1,7 +1,8 @@
""" """
TravisCI(; config_file::Union{AbstractString, Void}="") -> GenericPlugin TravisCI(; config_file::Union{AbstractString, Void}="") -> GenericPlugin
Add TravisCI to a template's plugins to add Travis CI support. Add `TravisCI` to a template's plugins to add a `.travis.yml` configuration file to
generated repositories, and an appropriate badge to the README.
# Keyword Arguments: # Keyword Arguments:
* `config_file::Union{AbstractString, Void}=""`: Path to a custom `.travis.yml`. * `config_file::Union{AbstractString, Void}=""`: Path to a custom `.travis.yml`.
@ -11,7 +12,7 @@ Add TravisCI to a template's plugins to add Travis CI support.
gitignore::Vector{AbstractString} gitignore::Vector{AbstractString}
src::Nullable{AbstractString} src::Nullable{AbstractString}
dest::AbstractString dest::AbstractString
badges::Vector{AbstractString} badges::Vector{Vector{AbstractString}}
view::Dict{String, Any} view::Dict{String, Any}
function TravisCI(; config_file::Union{AbstractString, Void}="") function TravisCI(; config_file::Union{AbstractString, Void}="")
@ -26,7 +27,13 @@ Add TravisCI to a template's plugins to add Travis CI support.
[], [],
config_file, config_file,
".travis.yml", ".travis.yml",
["[![Build Status](https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl.svg?branch=master)](https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl)"], [
[
"Build Status",
"https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl.svg?branch=master",
"https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl",
],
],
Dict{String, Any}(), Dict{String, Any}(),
) )
end end

View File

@ -3,7 +3,7 @@ using Base.Test
import PkgTemplates: badges, version_floor, substitute, read_license, gen_file, gen_readme, import PkgTemplates: badges, version_floor, substitute, read_license, gen_file, gen_readme,
gen_tests, gen_license, gen_require, gen_entrypoint, gen_gitignore, gen_plugin, gen_tests, gen_license, gen_require, gen_entrypoint, gen_gitignore, gen_plugin,
show_license, LICENSES, LICENSE_DIR show_license, LICENSES, LICENSE_DIR, GenericPlugin
mktempdir() do temp_dir mktempdir() do temp_dir
withenv("JULIA_PKGDIR" => temp_dir) do withenv("JULIA_PKGDIR" => temp_dir) do

View File

@ -1,3 +1,12 @@
struct Foo <: GenericPlugin
gitignore::Vector{AbstractString}
src::Nullable{AbstractString}
dest::AbstractString
badges::Vector{Vector{AbstractString}}
view::Dict{String, Any}
Foo() = new([], @__FILE__, "", [["foo", "bar", "baz"]], Dict{String, Any}())
end
const git_config = Dict( const git_config = Dict(
"user.name" => "Tester McTestFace", "user.name" => "Tester McTestFace",
"user.email" => "email@web.site", "user.email" => "email@web.site",
@ -11,6 +20,7 @@ template_text = """
VERSION: {{VERSION}}} VERSION: {{VERSION}}}
{{#DOCUMENTER}}Documenter{{/DOCUMENTER}} {{#DOCUMENTER}}Documenter{{/DOCUMENTER}}
{{#CODECOV}}CodeCov{{/CODECOV}} {{#CODECOV}}CodeCov{{/CODECOV}}
{{#CODECOV}}Coveralls{{/CODECOV}}
{{#AFTER}}After{{/AFTER}} {{#AFTER}}After{{/AFTER}}
{{#OTHER}}Other{{/OTHER}} {{#OTHER}}Other{{/OTHER}}
""" """
@ -70,11 +80,15 @@ write(test_file, template_text)
t = Template(; t = Template(;
user="invenia", user="invenia",
plugins = [GitHubPages(), TravisCI(), AppVeyor(), CodeCov()], plugins = [GitHubPages(), TravisCI(), AppVeyor(), CodeCov(), Coveralls()],
) )
rm(t.temp_dir; recursive=true) rm(t.temp_dir; recursive=true)
@test Set(keys(t.plugins)) == Set([GitHubPages, TravisCI, AppVeyor, CodeCov]) @test Set(keys(t.plugins)) == Set(
@test Set(values(t.plugins)) == Set([GitHubPages(), TravisCI(), AppVeyor(), CodeCov()]) [GitHubPages, TravisCI, AppVeyor, CodeCov, Coveralls]
)
@test Set(values(t.plugins)) == Set(
[GitHubPages(), TravisCI(), AppVeyor(), CodeCov(), Coveralls()]
)
@test_warn r".+" t = Template(; @test_warn r".+" t = Template(;
user="invenia", user="invenia",
@ -97,7 +111,11 @@ end
@test isempty(p.gitignore) @test isempty(p.gitignore)
@test get(p.src) == joinpath(PkgTemplates.DEFAULTS_DIR, "appveyor.yml") @test get(p.src) == joinpath(PkgTemplates.DEFAULTS_DIR, "appveyor.yml")
@test p.dest == ".appveyor.yml" @test p.dest == ".appveyor.yml"
@test p.badges == ["[![Build Status](https://ci.appveyor.com/api/projects/status/github/{{USER}}/{{PKGNAME}}.jl?svg=true)](https://ci.appveyor.com/project/{{USER}}/{{PKGNAME}}-jl)"] @test p.badges == [[
"Build Status",
"https://ci.appveyor.com/api/projects/status/github/{{USER}}/{{PKGNAME}}.jl?svg=true",
"https://ci.appveyor.com/project/{{USER}}/{{PKGNAME}}-jl",
]]
@test isempty(p.view) @test isempty(p.view)
p = AppVeyor(; config_file=nothing) p = AppVeyor(; config_file=nothing)
@test_throws NullException get(p.src) @test_throws NullException get(p.src)
@ -109,7 +127,11 @@ end
@test isempty(p.gitignore) @test isempty(p.gitignore)
@test get(p.src) == joinpath(PkgTemplates.DEFAULTS_DIR, "travis.yml") @test get(p.src) == joinpath(PkgTemplates.DEFAULTS_DIR, "travis.yml")
@test p.dest == ".travis.yml" @test p.dest == ".travis.yml"
@test p.badges == ["[![Build Status](https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl.svg?branch=master)](https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl)"] @test p.badges == [[
"Build Status",
"https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl.svg?branch=master",
"https://travis-ci.org/{{USER}}/{{PKGNAME}}.jl",
]]
@test isempty(p.view) @test isempty(p.view)
p = TravisCI(; config_file=nothing) p = TravisCI(; config_file=nothing)
@test_throws NullException get(p.src) @test_throws NullException get(p.src)
@ -121,7 +143,11 @@ end
@test p.gitignore == ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"] @test p.gitignore == ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"]
@test get(p.src) == joinpath(PkgTemplates.DEFAULTS_DIR, "codecov.yml") @test get(p.src) == joinpath(PkgTemplates.DEFAULTS_DIR, "codecov.yml")
@test p.dest == ".codecov.yml" @test p.dest == ".codecov.yml"
@test p.badges == ["[![CodeCov](https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl)"] @test p.badges == [[
"CodeCov",
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl/branch/master/graph/badge.svg",
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl",
]]
@test isempty(p.view) @test isempty(p.view)
p = CodeCov(; config_file=nothing) p = CodeCov(; config_file=nothing)
@test_throws NullException get(p.src) @test_throws NullException get(p.src)
@ -133,7 +159,11 @@ end
@test p.gitignore == ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"] @test p.gitignore == ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"]
@test_throws NullException get(p.src) @test_throws NullException get(p.src)
@test p.dest == ".coveralls.yml" @test p.dest == ".coveralls.yml"
@test p.badges == ["[![Coveralls](https://coveralls.io/repos/github/{{USER}}/{{PKGNAME}}.jl/badge.svg?branch=master)](https://coveralls.io/github/{{USER}}/{{PKGNAME}}.jl?branch=master)"] @test p.badges == [[
"Coveralls",
"https://coveralls.io/repos/github/{{USER}}/{{PKGNAME}}.jl/badge.svg?branch=master",
"https://coveralls.io/github/{{USER}}/{{PKGNAME}}.jl?branch=master",
]]
@test isempty(p.view) @test isempty(p.view)
p = Coveralls(; config_file=nothing) p = Coveralls(; config_file=nothing)
@test_throws NullException get(p.src) @test_throws NullException get(p.src)
@ -176,7 +206,7 @@ end
user="invenia", user="invenia",
license="MPL", license="MPL",
git_config=git_config, git_config=git_config,
plugins=[TravisCI(), CodeCov(), GitHubPages(), AppVeyor()], plugins=[Coveralls(), TravisCI(), CodeCov(), GitHubPages(), AppVeyor()],
) )
pkg_dir = joinpath(t.temp_dir, test_pkg) pkg_dir = joinpath(t.temp_dir, test_pkg)
@ -198,7 +228,14 @@ end
@test search(readme, "github.io").start < @test search(readme, "github.io").start <
search(readme, "travis").start < search(readme, "travis").start <
search(readme, "appveyor").start < search(readme, "appveyor").start <
search(readme, "codecov").start search(readme, "codecov").start <
search(readme, "coveralls").start
# Plugins with badges but not in BADGE_ORDER should appear at the far right side.
t.plugins[Foo] = Foo()
gen_readme(test_pkg, t)
readme = readchomp(joinpath(pkg_dir, "README.md"))
rm(joinpath(pkg_dir, "README.md"))
@test search(readme, "coveralls").start < search(readme, "baz").start
@test gen_gitignore(test_pkg, t) == [".gitignore"] @test gen_gitignore(test_pkg, t) == [".gitignore"]
@test isfile(joinpath(pkg_dir, ".gitignore")) @test isfile(joinpath(pkg_dir, ".gitignore"))
@ -326,6 +363,38 @@ end
p = TravisCI() p = TravisCI()
@test gen_plugin(p, t, test_pkg) == [".travis.yml"] @test gen_plugin(p, t, test_pkg) == [".travis.yml"]
@test isfile(joinpath(pkg_dir, ".travis.yml")) @test isfile(joinpath(pkg_dir, ".travis.yml"))
travis = readstring(joinpath(pkg_dir, ".travis.yml"))
@test !contains(travis, "after_success")
@test !contains(travis, "Codecov.submit")
@test !contains(travis, "Coveralls.submit")
@test !contains(travis, "Pkg.add(\"Documenter\")")
rm(joinpath(pkg_dir, ".travis.yml"))
t.plugins[CodeCov] = CodeCov()
gen_plugin(p, t, test_pkg)
delete!(t.plugins, CodeCov)
travis = readstring(joinpath(pkg_dir, ".travis.yml"))
@test contains(travis, "after_success")
@test contains(travis, "Codecov.submit")
@test !contains(travis, "Coveralls.submit")
@test !contains(travis, "Pkg.add(\"Documenter\")")
rm(joinpath(pkg_dir, ".travis.yml"))
t.plugins[Coveralls] = Coveralls()
gen_plugin(p, t, test_pkg)
delete!(t.plugins, Coveralls)
travis = readstring(joinpath(pkg_dir, ".travis.yml"))
@test contains(travis, "after_success")
@test contains(travis, "Coveralls.submit")
@test !contains(travis, "Codecov.submit")
@test !contains(travis, "Pkg.add(\"Documenter\")")
rm(joinpath(pkg_dir, ".travis.yml"))
t.plugins[GitHubPages] = GitHubPages()
gen_plugin(p, t, test_pkg)
delete!(t.plugins, GitHubPages)
travis = readstring(joinpath(pkg_dir, ".travis.yml"))
@test contains(travis, "after_success")
@test contains(travis, "Pkg.add(\"Documenter\")")
@test !contains(travis, "Codecov.submit")
@test !contains(travis, "Coveralls.submit")
rm(joinpath(pkg_dir, ".travis.yml")) rm(joinpath(pkg_dir, ".travis.yml"))
p = TravisCI(; config_file=nothing) p = TravisCI(; config_file=nothing)
@test isempty(gen_plugin(p, t, test_pkg)) @test isempty(gen_plugin(p, t, test_pkg))
@ -335,6 +404,26 @@ end
p = AppVeyor() p = AppVeyor()
@test gen_plugin(p, t, test_pkg) == [".appveyor.yml"] @test gen_plugin(p, t, test_pkg) == [".appveyor.yml"]
@test isfile(joinpath(pkg_dir, ".appveyor.yml")) @test isfile(joinpath(pkg_dir, ".appveyor.yml"))
appveyor = readstring(joinpath(pkg_dir, ".appveyor.yml"))
@test !contains(appveyor, "after_script")
@test !contains(appveyor, "Codecov.submit")
@test !contains(appveyor, "Coveralls.submit")
rm(joinpath(pkg_dir, ".appveyor.yml"))
t.plugins[CodeCov] = CodeCov()
gen_plugin(p, t, test_pkg)
delete!(t.plugins, CodeCov)
appveyor = readstring(joinpath(pkg_dir, ".appveyor.yml"))
@test contains(appveyor, "after_script")
@test contains(appveyor, "Codecov.submit")
@test !contains(appveyor, "Coveralls.submit")
rm(joinpath(pkg_dir, ".appveyor.yml"))
t.plugins[Coveralls] = Coveralls()
gen_plugin(p, t, test_pkg)
delete!(t.plugins, Coveralls)
appveyor = readstring(joinpath(pkg_dir, ".appveyor.yml"))
@test contains(appveyor, "after_script")
@test contains(appveyor, "Coveralls.submit")
@test !contains(appveyor, "Codecov.submit")
rm(joinpath(pkg_dir, ".appveyor.yml")) rm(joinpath(pkg_dir, ".appveyor.yml"))
p = AppVeyor(; config_file=nothing) p = AppVeyor(; config_file=nothing)
@test isempty(gen_plugin(p, t, test_pkg)) @test isempty(gen_plugin(p, t, test_pkg))
@ -393,12 +482,25 @@ end
end end
@testset "Mustache substitution" begin @testset "Mustache substitution" begin
view = Dict{String, Any}()
text = substitute(template_text, view)
@test !contains(text, "PKGNAME: $test_pkg")
@test !contains(text, "Documenter")
@test !contains(text, "CodeCov")
@test !contains(text, "Coveralls")
@test !contains(text, "After")
@test !contains(text, "Other")
view["PKGNAME"] = test_pkg
view["OTHER"] = true
text = substitute(template_text, view)
@test contains(text, "PKGNAME: $test_pkg")
@test contains(text, "Other")
t = Template(; user="invenia") t = Template(; user="invenia")
rm(t.temp_dir; recursive=true) rm(t.temp_dir; recursive=true)
p = Coveralls() view["OTHER"] = false
view = Dict{String, Any}("OTHER" => false)
text = substitute(template_text, t, test_pkg; view=view) text = substitute(template_text, t; view=view)
@test contains(text, "PKGNAME: $test_pkg") @test contains(text, "PKGNAME: $test_pkg")
@test contains(text, "VERSION: $(t.julia_version.major).$(t.julia_version.minor)") @test contains(text, "VERSION: $(t.julia_version.major).$(t.julia_version.minor)")
@test !contains(text, "Documenter") @test !contains(text, "Documenter")
@ -406,25 +508,25 @@ end
@test !contains(text, "Other") @test !contains(text, "Other")
t.plugins[GitHubPages] = GitHubPages() t.plugins[GitHubPages] = GitHubPages()
text = substitute(template_text, t, test_pkg; view=view) text = substitute(template_text, t; view=view)
@test contains(text, "Documenter") @test contains(text, "Documenter")
@test contains(text, "After") @test contains(text, "After")
empty!(t.plugins) empty!(t.plugins)
t.plugins[CodeCov] = CodeCov() t.plugins[CodeCov] = CodeCov()
text = substitute(template_text, t, test_pkg; view=view) text = substitute(template_text, t; view=view)
@test contains(text, "CodeCov") @test contains(text, "CodeCov")
@test contains(text, "After") @test contains(text, "After")
empty!(t.plugins) empty!(t.plugins)
t.plugins[CodeCov] = Coveralls()
text = substitute(template_text, t; view=view)
@test contains(text, "Coveralls")
@test contains(text, "After")
empty!(t.plugins)
view["OTHER"] = true view["OTHER"] = true
text = substitute(template_text, t, test_pkg; view=view) text = substitute(template_text, t; view=view)
@test contains(text, "Other")
text = substitute(template_text, p, test_pkg)
@test contains(text, "PKGNAME: $test_pkg")
text = substitute(template_text, p, test_pkg; view=view)
@test contains(text, "Other") @test contains(text, "Other")
end end