Remove interactive stuff (for now)
This commit is contained in:
parent
cce0f5a750
commit
5e9ff16cbe
@ -5,17 +5,15 @@ version = "0.7.0"
|
|||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||||
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
|
||||||
LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
||||||
Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
|
Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
|
||||||
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
|
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
|
||||||
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
||||||
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
|
||||||
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||||
|
|
||||||
[compat]
|
[compat]
|
||||||
julia = "1"
|
|
||||||
Mustache = ">= 0.5.13"
|
Mustache = ">= 0.5.13"
|
||||||
|
julia = "1"
|
||||||
|
|
||||||
[extras]
|
[extras]
|
||||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||||
|
@ -47,16 +47,10 @@ t = Template(;
|
|||||||
Codecov(),
|
Codecov(),
|
||||||
TravisCI(; x86=true),
|
TravisCI(; x86=true),
|
||||||
Documenter{TravisCI}(),
|
Documenter{TravisCI}(),
|
||||||
o ],
|
],
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also create a `Template` interactively by following a set of prompts:
|
|
||||||
|
|
||||||
```jl
|
|
||||||
julia> t = Template(; interactive=true)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
For a much more detailled overview, please see the documentation.
|
For a much more detailled overview, please see the documentation.
|
||||||
|
@ -19,7 +19,6 @@ BasicPlugin
|
|||||||
|
|
||||||
## Template + Package Creation Pipeline
|
## Template + Package Creation Pipeline
|
||||||
|
|
||||||
|
|
||||||
The [`Template`](@ref) constructor basically does this:
|
The [`Template`](@ref) constructor basically does this:
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -76,7 +75,7 @@ To understand how they're implemented, let's look at simplified versions of two
|
|||||||
### Example: `Documenter`
|
### Example: `Documenter`
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
@with_defaults struct Documenter <: Plugin
|
@with_kw_noshow struct Documenter <: Plugin
|
||||||
make_jl::String = default_file("docs", "make.jl") <- "Path to make.jl template"
|
make_jl::String = default_file("docs", "make.jl") <- "Path to make.jl template"
|
||||||
index_md::String = default_file("docs", "src", "index.md") <- "Path to index.md template"
|
index_md::String = default_file("docs", "src", "index.md") <- "Path to index.md template"
|
||||||
end
|
end
|
||||||
@ -118,14 +117,8 @@ function hook(p::Documenter, t::Template, pkg_dir::AbstractString)
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
The first thing you'll notice is the strange struct definition with [`@with_defaults`](@ref).
|
The `@with_kw_noshow` macro defines keyword constructors for us.
|
||||||
|
Inside of our struct definition, we're using [`default_file`](@ref) to refer to files in this repository.
|
||||||
```@docs
|
|
||||||
@with_defaults
|
|
||||||
interactive
|
|
||||||
```
|
|
||||||
|
|
||||||
Inside of our struct definition we're using [`default_file`](@ref) to refer to files in this repository.
|
|
||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
default_file
|
default_file
|
||||||
|
@ -43,16 +43,11 @@ One less name to remember!
|
|||||||
|
|
||||||
## Interactive Templates
|
## Interactive Templates
|
||||||
|
|
||||||
Two less names to remember!
|
Currently not implemented, but will be in the future.
|
||||||
|
|
||||||
| Old | New |
|
|
||||||
| :--------------------: | :---------------------------------: |
|
|
||||||
| `interactive_template` | `Template(; interactive=true)` |
|
|
||||||
| `generate_interactive` | `Template(; interactive=true)(pkg)` |
|
|
||||||
|
|
||||||
## Other Functions
|
## Other Functions
|
||||||
|
|
||||||
Another two less names to remember!
|
Two less names to remember!
|
||||||
Although it's unlikely that anyone used these.
|
Although it's unlikely that anyone used these.
|
||||||
|
|
||||||
| Old | New |
|
| Old | New |
|
||||||
|
@ -4,14 +4,12 @@ using Base: active_project
|
|||||||
using Base.Filesystem: contractuser
|
using Base.Filesystem: contractuser
|
||||||
|
|
||||||
using Dates: month, today, year
|
using Dates: month, today, year
|
||||||
using InteractiveUtils: subtypes
|
|
||||||
using LibGit2: LibGit2, GitRemote, GitRepo
|
using LibGit2: LibGit2, GitRemote, GitRepo
|
||||||
using Pkg: Pkg, TOML, PackageSpec
|
using Pkg: Pkg, TOML, PackageSpec
|
||||||
using REPL.TerminalMenus: MultiSelectMenu, RadioMenu, request
|
|
||||||
using UUIDs: uuid4
|
using UUIDs: uuid4
|
||||||
|
|
||||||
using Mustache: render
|
using Mustache: render
|
||||||
using Parameters: with_kw
|
using Parameters: @with_kw_noshow
|
||||||
|
|
||||||
export
|
export
|
||||||
Template,
|
Template,
|
||||||
@ -43,7 +41,6 @@ abstract type Plugin end
|
|||||||
include("template.jl")
|
include("template.jl")
|
||||||
include("plugin.jl")
|
include("plugin.jl")
|
||||||
include("show.jl")
|
include("show.jl")
|
||||||
include("interactive.jl")
|
|
||||||
|
|
||||||
# Run some function with a project activated at the given path.
|
# Run some function with a project activated at the given path.
|
||||||
function with_project(f::Function, path::AbstractString)
|
function with_project(f::Function, path::AbstractString)
|
||||||
|
@ -1,172 +0,0 @@
|
|||||||
"""
|
|
||||||
interactive(::Type{T<:Plugin}) -> T
|
|
||||||
|
|
||||||
Create a [`Plugin`](@ref) of type `T` interactively from user input.
|
|
||||||
"""
|
|
||||||
function interactive(::Type{T}) where T <: Plugin
|
|
||||||
kwargs = Dict{Symbol, Any}()
|
|
||||||
|
|
||||||
foreach(fieldnames(T)) do name
|
|
||||||
F = fieldtype(T, name)
|
|
||||||
v = Val(name)
|
|
||||||
required = !applicable(defaultkw, T, v)
|
|
||||||
default = required ? defaultkw(F) : defaultkw(T, v)
|
|
||||||
kwargs[name] = if applicable(prompt, T, v)
|
|
||||||
prompt(F, "$T: $(prompt(T, v))", default, required=required)
|
|
||||||
elseif required
|
|
||||||
prompt(F, "$T: Value for field '$name' ($F)", default; required=required)
|
|
||||||
else
|
|
||||||
default
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return T(; kwargs...)
|
|
||||||
end
|
|
||||||
|
|
||||||
leaves(T::Type) = isconcretetype(T) ? [T] : vcat(map(leaves, subtypes(T))...)
|
|
||||||
|
|
||||||
function plugin_types()
|
|
||||||
Ts = leaves(Plugin)
|
|
||||||
# Hack both Documenter types into the list.
|
|
||||||
# Unfortunately there's no way to do this automatically,
|
|
||||||
# but it's unlikely for more parametric plugin types to exist.
|
|
||||||
push!(Ts, Documenter{TravisCI}, Documenter{GitLabCI})
|
|
||||||
return Ts
|
|
||||||
end
|
|
||||||
|
|
||||||
function Template(::Val{true}; kwargs...)
|
|
||||||
opts = Dict{Symbol, Any}(kwargs)
|
|
||||||
|
|
||||||
if !haskey(opts, :user)
|
|
||||||
default = defaultkw(Template, :user)
|
|
||||||
opts[:user] = prompt(String, "Git hosting service username", default)
|
|
||||||
end
|
|
||||||
|
|
||||||
if !haskey(opts, :host)
|
|
||||||
default = defaultkw(Template, :host)
|
|
||||||
opts[:host] = prompt(String, "Git hosting service URL", default)
|
|
||||||
end
|
|
||||||
|
|
||||||
if !haskey(opts, :authors)
|
|
||||||
default = defaultkw(Template, :authors)
|
|
||||||
opts[:authors] = prompt(String, "Package author(s)", default)
|
|
||||||
end
|
|
||||||
|
|
||||||
if !haskey(opts, :dir)
|
|
||||||
default = defaultkw(Template, :dir)
|
|
||||||
opts[:dir] = prompt(String, "Path to package parent directory", default)
|
|
||||||
end
|
|
||||||
|
|
||||||
if !haskey(opts, :julia)
|
|
||||||
default = defaultkw(Template, :julia)
|
|
||||||
opts[:julia] = prompt(VersionNumber, "Supported Julia version", default)
|
|
||||||
end
|
|
||||||
|
|
||||||
if !haskey(opts, :disable_defaults)
|
|
||||||
available = map(typeof, default_plugins())
|
|
||||||
initial = defaultkw(Template, :disable_defaults)
|
|
||||||
opts[:disable_defaults] = select("Select defaults to disable:", available, initial)
|
|
||||||
end
|
|
||||||
|
|
||||||
if !haskey(opts, :plugins)
|
|
||||||
# Don't offer any disabled plugins as options.
|
|
||||||
available = setdiff(sort(plugin_types(); by=string), opts[:disable_defaults])
|
|
||||||
initial = setdiff(map(typeof, default_plugins()), opts[:disable_defaults])
|
|
||||||
chosen = select("Select plugins", available, initial)
|
|
||||||
opts[:plugins] = map(interactive, chosen)
|
|
||||||
end
|
|
||||||
|
|
||||||
return Template(Val(false); opts...)
|
|
||||||
end
|
|
||||||
|
|
||||||
defaultkw(::Type{String}) = ""
|
|
||||||
defaultkw(::Type{Union{T, Nothing}}) where T = nothing
|
|
||||||
defaultkw(::Type{T}) where T <: Number = zero(T)
|
|
||||||
defaultkw(::Type{Vector{T}}) where T = T[]
|
|
||||||
|
|
||||||
function prompt(
|
|
||||||
::Type{<:Union{String, Nothing}}, s::AbstractString, default;
|
|
||||||
required::Bool=false,
|
|
||||||
)
|
|
||||||
default isa AbstractString && (default = contractuser(default))
|
|
||||||
default_display = if required
|
|
||||||
"REQUIRED"
|
|
||||||
elseif default === nothing
|
|
||||||
"None"
|
|
||||||
else
|
|
||||||
repr(default)
|
|
||||||
end
|
|
||||||
|
|
||||||
print("$s [$default_display]: ")
|
|
||||||
input = strip(readline())
|
|
||||||
|
|
||||||
return if isempty(input) && required
|
|
||||||
println("This option is required")
|
|
||||||
prompt(String, s, default; required=required)
|
|
||||||
elseif isempty(input)
|
|
||||||
default
|
|
||||||
else
|
|
||||||
input
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function prompt(
|
|
||||||
::Type{VersionNumber}, s::AbstractString, default::VersionNumber;
|
|
||||||
required::Bool=false,
|
|
||||||
)
|
|
||||||
v = prompt(String, s, default; required=required)
|
|
||||||
return if v isa VersionNumber
|
|
||||||
v
|
|
||||||
else
|
|
||||||
startswith(v, "v") && (v = v[2:end])
|
|
||||||
v = replace(v, "\"" => "")
|
|
||||||
VersionNumber(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function prompt(::Type{Bool}, s::AbstractString, default::Bool; required::Bool=false)
|
|
||||||
b = prompt(String, s, default; required=required)
|
|
||||||
return b === default ? default : uppercase(b) in ("Y", "YES", "T", "TRUE")
|
|
||||||
end
|
|
||||||
|
|
||||||
function prompt(::Type{Vector}, s::AbstractString, default::Vector; required::Bool=false)
|
|
||||||
return prompt(Vector{String}, s, default; required=required)
|
|
||||||
end
|
|
||||||
|
|
||||||
function prompt(
|
|
||||||
::Type{Vector{String}}, s::AbstractString, default::Vector{<:AbstractString};
|
|
||||||
required::Bool=false,
|
|
||||||
)
|
|
||||||
s = prompt(String, "$s (comma-delimited)", join(default, ", "); required=required)
|
|
||||||
return convert(Vector{String}, map(strip, split(s, ","; keepempty=false)))
|
|
||||||
end
|
|
||||||
|
|
||||||
function prompt(::Type{<:Dict}, s::AbstractString, default::Dict, required::Bool=false)
|
|
||||||
default_display = join(map(p -> "$(p.first)=$(p.second)", collect(default)), ", ")
|
|
||||||
s = prompt(String, "$s (k=v, comma-delimited)", default_display; required=required)
|
|
||||||
return if isempty(s)
|
|
||||||
Dict{String, String}()
|
|
||||||
else
|
|
||||||
Dict{String, String}(Pair(split(strip(kv), "=")...) for kv in split(s, ","))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: These can be made simpler when this is merged:
|
|
||||||
# https://github.com/JuliaLang/julia/pull/30043
|
|
||||||
|
|
||||||
select(s::AbstractString, xs::Vector, initial) = select(string, s, xs, initial)
|
|
||||||
|
|
||||||
# Select any number of elements from a collection.
|
|
||||||
function select(f::Function, s::AbstractString, xs::Vector, initial::Vector)
|
|
||||||
m = MultiSelectMenu(map(f, xs); pagesize=length(xs))
|
|
||||||
foreach(x -> push!(m.selected, findfirst(==(x), xs)), initial)
|
|
||||||
selection = request("$s:", m)
|
|
||||||
return map(i -> xs[i], collect(selection))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Select one item frm oa collection.
|
|
||||||
function select(f::Function, s::AbstractString, xs::Vector, initial)
|
|
||||||
print(stdin.buffer, repeat("\e[B", findfirst(==(initial), xs) - 1))
|
|
||||||
selection = request("$s:", RadioMenu(map(f, xs); pagesize=length(xs)))
|
|
||||||
return xs[selection]
|
|
||||||
end
|
|
@ -1,47 +1,6 @@
|
|||||||
const TEMPLATES_DIR = normpath(joinpath(@__DIR__, "..", "templates"))
|
const TEMPLATES_DIR = normpath(joinpath(@__DIR__, "..", "templates"))
|
||||||
const DEFAULT_PRIORITY = 1000
|
const DEFAULT_PRIORITY = 1000
|
||||||
|
|
||||||
"""
|
|
||||||
@with_defaults struct T #= ... =# end
|
|
||||||
|
|
||||||
Creates keyword constructors and generates methods needed to interactively create instances with [`interactive`](@ref).
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```julia
|
|
||||||
struct Foo <: Plugin
|
|
||||||
file::String = "/the/default/value" <- "This is the interactive prompt"
|
|
||||||
n::Int <- "This one has no default, so it's a required keyword"
|
|
||||||
abc::String = "No prompt, so the default is always taken in interactive mode"
|
|
||||||
xyz::String # Required keyword, with a generic interactive prompt.
|
|
||||||
end
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
macro with_defaults(ex::Expr)
|
|
||||||
T = esc(ex.args[2].args[1]) # This assumes T <: U.
|
|
||||||
|
|
||||||
# This is a bit nasty.
|
|
||||||
funcs = Expr[]
|
|
||||||
foreach(filter(arg -> arg isa Expr, ex.args[3].args)) do arg
|
|
||||||
if iscall(arg, :<) && iscall(arg.args[3], :-) # x::T <- "prompt"
|
|
||||||
name = QuoteNode(arg.args[2].args[1])
|
|
||||||
prompt = arg.args[2]
|
|
||||||
push!(funcs, :(PkgTemplates.prompt(::Type{$T}, ::Val{$name}) = $(esc(prompt))))
|
|
||||||
elseif arg.head === :(=)
|
|
||||||
rhs = arg.args[2]
|
|
||||||
name = QuoteNode(arg.args[1].args[1])
|
|
||||||
if iscall(rhs, :<) && iscall(rhs.args[3], :-) # x::T = "foo" <- "prompt"
|
|
||||||
prompt = rhs.args[3].args[2]
|
|
||||||
push!(funcs, :(PkgTemplates.prompt(::Type{$T}, ::Val{$name}) = $(esc(prompt))))
|
|
||||||
end
|
|
||||||
default = arg.args[2] = rhs.args[2]
|
|
||||||
push!(funcs, :(PkgTemplates.defaultkw(::Type{$T}, ::Val{$name}) = $(esc(default))))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return Expr(:block, esc(with_kw(ex, __module__, false)), funcs...)
|
|
||||||
end
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
A simple plugin that, in general, creates a single file.
|
A simple plugin that, in general, creates a single file.
|
||||||
"""
|
"""
|
||||||
@ -276,11 +235,6 @@ If you are implementing a plugin that uses the `user` field of a [`Template`](@r
|
|||||||
"""
|
"""
|
||||||
needs_username(::Plugin) = false
|
needs_username(::Plugin) = false
|
||||||
|
|
||||||
function prompt end
|
|
||||||
|
|
||||||
iscall(x, ::Symbol) = false
|
|
||||||
iscall(ex::Expr, s::Symbol) = ex.head === :call && ex.args[1] === s
|
|
||||||
|
|
||||||
include(joinpath("plugins", "project_file.jl"))
|
include(joinpath("plugins", "project_file.jl"))
|
||||||
include(joinpath("plugins", "src_dir.jl"))
|
include(joinpath("plugins", "src_dir.jl"))
|
||||||
include(joinpath("plugins", "tests.jl"))
|
include(joinpath("plugins", "tests.jl"))
|
||||||
|
@ -9,6 +9,7 @@ format_version(v::AbstractString) = string(v)
|
|||||||
|
|
||||||
const ALLOWED_FAILURES = ["1.3", "nightly"] # TODO: Update this list with new RCs.
|
const ALLOWED_FAILURES = ["1.3", "nightly"] # TODO: Update this list with new RCs.
|
||||||
const DEFAULT_CI_VERSIONS = map(format_version, [default_version(), VERSION, "nightly"])
|
const DEFAULT_CI_VERSIONS = map(format_version, [default_version(), VERSION, "nightly"])
|
||||||
|
const DEFAULT_CI_VERSIONS_NO_NIGHTLY = map(format_version, [default_version(), VERSION])
|
||||||
const EXTRA_VERSIONS_DOC = "- `extra_versions::Vector`: Extra Julia versions to test, as strings or `VersionNumber`s."
|
const EXTRA_VERSIONS_DOC = "- `extra_versions::Vector`: Extra Julia versions to test, as strings or `VersionNumber`s."
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -44,14 +45,14 @@ Integrates your packages with [Travis CI](https://travis-ci.com).
|
|||||||
- `coverage::Bool`: Whether or not to publish code coverage (another code coverage plugin such as [`Codecov`](@ref) must also be included).
|
- `coverage::Bool`: Whether or not to publish code coverage (another code coverage plugin such as [`Codecov`](@ref) must also be included).
|
||||||
$EXTRA_VERSIONS_DOC
|
$EXTRA_VERSIONS_DOC
|
||||||
"""
|
"""
|
||||||
@with_defaults struct TravisCI <: BasicPlugin
|
@with_kw_noshow struct TravisCI <: BasicPlugin
|
||||||
file::String = default_file("travis.yml") <- "Path to .travis.yml template"
|
file::String = default_file("travis.yml")
|
||||||
linux::Bool = true <- "Enable Linux bulds"
|
linux::Bool = true
|
||||||
osx::Bool = true <- "Enable OSX builds"
|
osx::Bool = true
|
||||||
windows::Bool = true <- "Enable Windows builds"
|
windows::Bool = true
|
||||||
x86::Bool = false <- "Enable 32-bit builds"
|
x86::Bool = false
|
||||||
coverage::Bool = true <- "Enable code coverage submission"
|
coverage::Bool = true
|
||||||
extra_versions::Vector = DEFAULT_CI_VERSIONS <- "Extra Julia versions to test"
|
extra_versions::Vector = DEFAULT_CI_VERSIONS
|
||||||
end
|
end
|
||||||
|
|
||||||
source(p::TravisCI) = p.file
|
source(p::TravisCI) = p.file
|
||||||
@ -113,11 +114,11 @@ Integrates your packages with [AppVeyor](https://appveyor.com) via [AppVeyor.jl]
|
|||||||
- `coverage::Bool`: Whether or not to publish code coverage ([`Codecov`](@ref) must also be included).
|
- `coverage::Bool`: Whether or not to publish code coverage ([`Codecov`](@ref) must also be included).
|
||||||
$EXTRA_VERSIONS_DOC
|
$EXTRA_VERSIONS_DOC
|
||||||
"""
|
"""
|
||||||
@with_defaults struct AppVeyor <: BasicPlugin
|
@with_kw_noshow struct AppVeyor <: BasicPlugin
|
||||||
file::String = default_file("appveyor.yml") <- "Path to .appveyor.yml template"
|
file::String = default_file("appveyor.yml")
|
||||||
x86::Bool = false <- "Enable 32-bit builds"
|
x86::Bool = false
|
||||||
coverage::Bool = true <- "Enable code coverage submission"
|
coverage::Bool = true
|
||||||
extra_versions::Vector = DEFAULT_CI_VERSIONS <- "Extra Julia versions to test"
|
extra_versions::Vector = DEFAULT_CI_VERSIONS
|
||||||
end
|
end
|
||||||
|
|
||||||
source(p::AppVeyor) = p.file
|
source(p::AppVeyor) = p.file
|
||||||
@ -166,11 +167,11 @@ $EXTRA_VERSIONS_DOC
|
|||||||
!!! note
|
!!! note
|
||||||
Code coverage submission from Cirrus CI is not yet supported by [Coverage.jl](https://github.com/JuliaCI/Coverage.jl).
|
Code coverage submission from Cirrus CI is not yet supported by [Coverage.jl](https://github.com/JuliaCI/Coverage.jl).
|
||||||
"""
|
"""
|
||||||
@with_defaults struct CirrusCI <: BasicPlugin
|
@with_kw_noshow struct CirrusCI <: BasicPlugin
|
||||||
file::String = default_file("cirrus.yml") <- "Path to .cirrus.yml template"
|
file::String = default_file("cirrus.yml")
|
||||||
image::String = "freebsd-12-0-release-amd64" <- "FreeBSD image"
|
image::String = "freebsd-12-0-release-amd64"
|
||||||
coverage::Bool = true <- "Enable code coverage submission"
|
coverage::Bool = true
|
||||||
extra_versions::Vector = DEFAULT_CI_VERSIONS <- "Extra Julia versions to test"
|
extra_versions::Vector = DEFAULT_CI_VERSIONS
|
||||||
end
|
end
|
||||||
|
|
||||||
source(p::CirrusCI) = p.file
|
source(p::CirrusCI) = p.file
|
||||||
@ -198,7 +199,7 @@ end
|
|||||||
GitLabCI(;
|
GitLabCI(;
|
||||||
file="$(contractuser(default_file("gitlab-ci.yml")))",
|
file="$(contractuser(default_file("gitlab-ci.yml")))",
|
||||||
coverage=true,
|
coverage=true,
|
||||||
extra_versions=$(map(format_version, [default_version(), VERSION])),
|
extra_versions=$DEFAULT_CI_VERSIONS_NO_NIGHTLY,
|
||||||
)
|
)
|
||||||
|
|
||||||
Integrates your packages with [GitLab CI](https://docs.gitlab.com/ce/ci/).
|
Integrates your packages with [GitLab CI](https://docs.gitlab.com/ce/ci/).
|
||||||
@ -215,11 +216,11 @@ See [`Documenter`](@ref) for more information.
|
|||||||
!!! note
|
!!! note
|
||||||
Nightly Julia is not supported.
|
Nightly Julia is not supported.
|
||||||
"""
|
"""
|
||||||
@with_defaults struct GitLabCI <: BasicPlugin
|
@with_kw_noshow struct GitLabCI <: BasicPlugin
|
||||||
file::String = default_file("gitlab-ci.yml") <- "Path to .gitlab-ci.yml template"
|
file::String = default_file("gitlab-ci.yml")
|
||||||
coverage::Bool = true <- "Enable code coverage submission"
|
coverage::Bool = true
|
||||||
# Nightly has no Docker image.
|
# Nightly has no Docker image.
|
||||||
extra_versions::Vector = map(format_version, [default_version(), VERSION]) <- "Extra Julia versions to test"
|
extra_versions::Vector = DEFAULT_CI_VERSIONS_NO_NIGHTLY
|
||||||
end
|
end
|
||||||
|
|
||||||
gitignore(p::GitLabCI) = p.coverage ? COVERAGE_GITIGNORE : String[]
|
gitignore(p::GitLabCI) = p.coverage ? COVERAGE_GITIGNORE : String[]
|
||||||
@ -252,7 +253,6 @@ function view(p::GitLabCI, t::Template, pkg::AbstractString)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
is_ci(::Plugin) -> Bool
|
is_ci(::Plugin) -> Bool
|
||||||
|
|
||||||
|
@ -7,9 +7,9 @@ Creates a `CITATION.bib` file for citing package repositories.
|
|||||||
- `file::AbstractString`: Template file for `CITATION.bib`.
|
- `file::AbstractString`: Template file for `CITATION.bib`.
|
||||||
- `readme::Bool`: Whether or not to include a section about citing in the README.
|
- `readme::Bool`: Whether or not to include a section about citing in the README.
|
||||||
"""
|
"""
|
||||||
@with_defaults struct Citation <: BasicPlugin
|
@with_kw_noshow struct Citation <: BasicPlugin
|
||||||
file::String = default_file("CITATION.bib") <- "Path to CITATION.bib template"
|
file::String = default_file("CITATION.bib")
|
||||||
readme::Bool = false <- """Enable "Citing" README section"""
|
readme::Bool = false
|
||||||
end
|
end
|
||||||
|
|
||||||
tags(::Citation) = "<<", ">>"
|
tags(::Citation) = "<<", ">>"
|
||||||
|
@ -8,8 +8,8 @@ Sets up code coverage submission from CI to [Codecov](https://codecov.io).
|
|||||||
## Keyword Arguments
|
## Keyword Arguments
|
||||||
- `file::Union{AbstractString, Nothing}`: Template file for `.codecov.yml`, or `nothing` to create no file.
|
- `file::Union{AbstractString, Nothing}`: Template file for `.codecov.yml`, or `nothing` to create no file.
|
||||||
"""
|
"""
|
||||||
@with_defaults struct Codecov <: BasicPlugin
|
@with_kw_noshow struct Codecov <: BasicPlugin
|
||||||
file::Union{String, Nothing} = nothing <- "Path to .codecov.yml template"
|
file::Union{String, Nothing} = nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
source(p::Codecov) = p.file
|
source(p::Codecov) = p.file
|
||||||
@ -29,8 +29,8 @@ Sets up code coverage submission from CI to [Coveralls](https://coveralls.io).
|
|||||||
## Keyword Arguments
|
## Keyword Arguments
|
||||||
- `file::Union{AbstractString, Nothing}`: Template file for `.coveralls.yml`, or `nothing` to create no file.
|
- `file::Union{AbstractString, Nothing}`: Template file for `.coveralls.yml`, or `nothing` to create no file.
|
||||||
"""
|
"""
|
||||||
@with_defaults struct Coveralls <: BasicPlugin
|
@with_kw_noshow struct Coveralls <: BasicPlugin
|
||||||
file::Union{String, Nothing} = nothing <- "Path to .coveralls.yml template"
|
file::Union{String, Nothing} = nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
source(p::Coveralls) = p.file
|
source(p::Coveralls) = p.file
|
||||||
|
@ -38,7 +38,7 @@ struct Documenter{T<:Union{TravisCI, GitLabCI, Nothing}} <: Plugin
|
|||||||
make_jl::String
|
make_jl::String
|
||||||
index_md::String
|
index_md::String
|
||||||
|
|
||||||
# Can't use @with_defaults due to some weird precompilation issues.
|
# Can't use @with_kw_noshow due to some weird precompilation issues.
|
||||||
function Documenter{T}(;
|
function Documenter{T}(;
|
||||||
assets::Vector{<:AbstractString}=String[],
|
assets::Vector{<:AbstractString}=String[],
|
||||||
makedocs_kwargs::Dict{Symbol}=Dict{Symbol, Any}(),
|
makedocs_kwargs::Dict{Symbol}=Dict{Symbol, Any}(),
|
||||||
@ -52,28 +52,6 @@ end
|
|||||||
|
|
||||||
Documenter(; kwargs...) = Documenter{Nothing}(; kwargs...)
|
Documenter(; kwargs...) = Documenter{Nothing}(; kwargs...)
|
||||||
|
|
||||||
function interactive(::Type{Documenter})
|
|
||||||
kwargs = Dict{Symbol, Any}()
|
|
||||||
|
|
||||||
default = default_file("docs", "make.jl")
|
|
||||||
kwargs[:make_jl] = prompt(String, "Documenter: Path to make.jl template", default)
|
|
||||||
|
|
||||||
default = default_file("docs", "src", "index.md")
|
|
||||||
kwargs[:index_md] = prompt(String, "Documenter: Path to make.jl template", default)
|
|
||||||
|
|
||||||
kwargs[:assets] = prompt(Vector{String}, "Documenter: Extra asset files", String[])
|
|
||||||
|
|
||||||
md_kw = prompt(Dict{String, String}, "Documenter: makedocs keyword arguments", Dict())
|
|
||||||
parsed = Dict{Symbol, Any}(Symbol(p.first) => eval(Meta.parse(p.second)) for p in md_kw)
|
|
||||||
kwargs[:makedocs_kwargs] = parsed
|
|
||||||
|
|
||||||
available = [Nothing, TravisCI, GitLabCI]
|
|
||||||
f = T -> string(nameof(T))
|
|
||||||
T = select(f, "Documenter: Documentation deployment strategy", available, Nothing)
|
|
||||||
|
|
||||||
return Documenter{T}(; kwargs...)
|
|
||||||
end
|
|
||||||
|
|
||||||
gitignore(::Documenter) = ["/docs/build/"]
|
gitignore(::Documenter) = ["/docs/build/"]
|
||||||
|
|
||||||
badges(::Documenter) = Badge[]
|
badges(::Documenter) = Badge[]
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
"""
|
|
||||||
DroneCI(; config_file::Union{AbstractString, Nothing}="") -> DroneCI
|
|
||||||
|
|
||||||
Add `DroneCI` to a template's plugins to add a `.drone.yml` configuration file to
|
|
||||||
generated repositories, and an appropriate badge to the README. The default configuration
|
|
||||||
file supports Linux on ARM32 and ARM64.
|
|
||||||
|
|
||||||
# Keyword Arguments
|
|
||||||
* `config_file::Union{AbstractString, Nothing}=""`: Path to a custom `.drone.yml`.
|
|
||||||
If `nothing` is supplied, no file will be generated.
|
|
||||||
"""
|
|
||||||
struct DroneCI <: GenericPlugin
|
|
||||||
gitignore::Vector{String}
|
|
||||||
src::Union{String, Nothing}
|
|
||||||
dest::String
|
|
||||||
badges::Vector{Badge}
|
|
||||||
view::Dict{String, Any}
|
|
||||||
|
|
||||||
function DroneCI(; config_file::Union{AbstractString, Nothing}="")
|
|
||||||
if config_file !== nothing
|
|
||||||
config_file = if isempty(config_file)
|
|
||||||
joinpath(DEFAULTS_DIR, "drone.yml")
|
|
||||||
elseif isfile(config_file)
|
|
||||||
abspath(config_file)
|
|
||||||
else
|
|
||||||
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return new(
|
|
||||||
[],
|
|
||||||
config_file,
|
|
||||||
".drone.yml",
|
|
||||||
[
|
|
||||||
Badge(
|
|
||||||
"Build Status",
|
|
||||||
"https://cloud.drone.io/api/badges/{{USER}}/{{PKGNAME}}.jl/status.svg",
|
|
||||||
"https://cloud.drone.io/{{USER}}/{{PKGNAME}}.jl",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
Dict{String, Any}(),
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
interactive(::Type{DroneCI}) = interactive(DroneCI; file="drone.yml")
|
|
@ -12,11 +12,11 @@ Creates a Git repository and a `.gitignore` file.
|
|||||||
- `gpgsign::Bool`: Whether or not to sign commits with your GPG key.
|
- `gpgsign::Bool`: Whether or not to sign commits with your GPG key.
|
||||||
This option requires that the Git CLI is installed, and for you to have a GPG key associated with your committer identity.
|
This option requires that the Git CLI is installed, and for you to have a GPG key associated with your committer identity.
|
||||||
"""
|
"""
|
||||||
@with_defaults struct Git <: Plugin
|
@with_kw_noshow struct Git <: Plugin
|
||||||
ignore::Vector{String} = String[] <- "Gitignore entries"
|
ignore::Vector{String} = String[]
|
||||||
ssh::Bool = false <- "Enable SSH Git remote"
|
ssh::Bool = false
|
||||||
manifest::Bool = false <- "Commit Manifest.toml"
|
manifest::Bool = false
|
||||||
gpgsign::Bool = false <- "GPG-sign commits"
|
gpgsign::Bool = false
|
||||||
end
|
end
|
||||||
|
|
||||||
# Try to make sure that no files are created after we commit.
|
# Try to make sure that no files are created after we commit.
|
||||||
|
@ -34,15 +34,3 @@ view(::License, t::Template, ::AbstractString) = Dict(
|
|||||||
"AUTHORS" => join(t.authors, ", "),
|
"AUTHORS" => join(t.authors, ", "),
|
||||||
"YEAR" => year(today()),
|
"YEAR" => year(today()),
|
||||||
)
|
)
|
||||||
|
|
||||||
function interactive(::Type{License})
|
|
||||||
destination = prompt(String, "License: License file destination", "LICENSE")
|
|
||||||
return if prompt(Bool, "License: Use custom license file", false)
|
|
||||||
path = prompt(String, "License: Path to custom license file", ""; required=true)
|
|
||||||
License(; path=path, destination=destination)
|
|
||||||
else
|
|
||||||
available = sort(readdir(joinpath(TEMPLATES_DIR, "licenses")))
|
|
||||||
name = select("License: Select a license", available, "MIT")
|
|
||||||
License(; name=name, destination=destination)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
inline_badges=false,
|
inline_badges=false,
|
||||||
)
|
)
|
||||||
|
|
||||||
Creates a `README` file.
|
Creates a `README` file that contains badges for other included plugins.
|
||||||
By default, it includes badges for other included plugins
|
|
||||||
|
|
||||||
## Keyword Arguments
|
## Keyword Arguments
|
||||||
- `file::AbstractString`: Template file for the `README`.
|
- `file::AbstractString`: Template file for the `README`.
|
||||||
@ -14,10 +13,10 @@ By default, it includes badges for other included plugins
|
|||||||
For example, values of `"README"` or `"README.rst"` might be desired.
|
For example, values of `"README"` or `"README.rst"` might be desired.
|
||||||
- `inline_badges::Bool`: Whether or not to put the badges on the same line as the package name.
|
- `inline_badges::Bool`: Whether or not to put the badges on the same line as the package name.
|
||||||
"""
|
"""
|
||||||
@with_defaults struct Readme <: BasicPlugin
|
@with_kw_noshow struct Readme <: BasicPlugin
|
||||||
file::String = default_file("README.md") <- "Path to README.md template"
|
file::String = default_file("README.md")
|
||||||
destination::String = "README.md" <- "README file destination"
|
destination::String = "README.md"
|
||||||
inline_badges::Bool = false <- "Enable inline badges"
|
inline_badges::Bool = false
|
||||||
end
|
end
|
||||||
|
|
||||||
source(p::Readme) = p.file
|
source(p::Readme) = p.file
|
||||||
|
@ -6,9 +6,9 @@ Creates a module entrypoint.
|
|||||||
## Keyword Arguments
|
## Keyword Arguments
|
||||||
- `file::AbstractString`: Template file for `src/<module>.jl`.
|
- `file::AbstractString`: Template file for `src/<module>.jl`.
|
||||||
"""
|
"""
|
||||||
@with_defaults mutable struct SrcDir <: BasicPlugin
|
@with_kw_noshow mutable struct SrcDir <: BasicPlugin
|
||||||
file::String = default_file("src", "module.jl") <- "Path to <module>.jl template"
|
file::String = default_file("src", "module.jl")
|
||||||
destination::String = joinpath("src", "<module>.jl")
|
destination::String = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
Base.:(==)(a::SrcDir, b::SrcDir) = a.file == b.file
|
Base.:(==)(a::SrcDir, b::SrcDir) = a.file == b.file
|
||||||
|
@ -14,9 +14,9 @@ Sets up testing for packages.
|
|||||||
!!! note
|
!!! note
|
||||||
Managing test dependencies with `test/Project.toml` is only supported in Julia 1.2 and later.
|
Managing test dependencies with `test/Project.toml` is only supported in Julia 1.2 and later.
|
||||||
"""
|
"""
|
||||||
@with_defaults struct Tests <: BasicPlugin
|
@with_kw_noshow struct Tests <: BasicPlugin
|
||||||
file::String = default_file("test", "runtests.jl") <- "Path to runtests.jl template"
|
file::String = default_file("test", "runtests.jl")
|
||||||
project::Bool = false <- "Enable test/Project.toml"
|
project::Bool = false
|
||||||
end
|
end
|
||||||
|
|
||||||
source(p::Tests) = p.file
|
source(p::Tests) = p.file
|
||||||
|
@ -34,9 +34,6 @@ A configuration used to generate packages.
|
|||||||
The default plugins are [`ProjectFile`](@ref), [`SrcDir`](@ref), [`Tests`](@ref), [`Readme`](@ref), [`License`](@ref), and [`Git`](@ref).
|
The default plugins are [`ProjectFile`](@ref), [`SrcDir`](@ref), [`Tests`](@ref), [`Readme`](@ref), [`License`](@ref), and [`Git`](@ref).
|
||||||
To override a default plugin instead of disabling it altogether, supply it via `plugins`.
|
To override a default plugin instead of disabling it altogether, supply it via `plugins`.
|
||||||
|
|
||||||
### Interactive Usage
|
|
||||||
- `interactive::Bool=false`: When set, the template is created interactively, filling unset keywords with user input.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
To create a package from a `Template`, use the following syntax:
|
To create a package from a `Template`, use the following syntax:
|
||||||
@ -56,7 +53,7 @@ struct Template
|
|||||||
user::String
|
user::String
|
||||||
end
|
end
|
||||||
|
|
||||||
Template(; interactive::Bool=false, kwargs...) = Template(Val(interactive); kwargs...)
|
Template(; kwargs...) = Template(Val(false); kwargs...)
|
||||||
|
|
||||||
# Non-interactive constructor.
|
# Non-interactive constructor.
|
||||||
function Template(::Val{false}; kwargs...)
|
function Template(::Val{false}; kwargs...)
|
||||||
|
29
test/fixtures/AllPlugins/drone.yml
vendored
29
test/fixtures/AllPlugins/drone.yml
vendored
@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
name: linux - arm - Julia {{VERSION}}
|
|
||||||
|
|
||||||
platform:
|
|
||||||
os: linux
|
|
||||||
arch: arm
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build
|
|
||||||
image: julia:{{VERSION}}
|
|
||||||
commands:
|
|
||||||
- "julia --project=. --check-bounds=yes --color=yes -e 'using InteractiveUtils; versioninfo(verbose=true); using Pkg; Pkg.build(); Pkg.test(coverage=true)'"
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
name: linux - arm64 - Julia {{VERSION}}
|
|
||||||
|
|
||||||
platform:
|
|
||||||
os: linux
|
|
||||||
arch: arm64
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build
|
|
||||||
image: julia:{{VERSION}}
|
|
||||||
commands:
|
|
||||||
- "julia --project=. --check-bounds=yes --color=yes -e 'using InteractiveUtils; versioninfo(verbose=true); using Pkg; Pkg.build(); Pkg.test(coverage=true)'"
|
|
||||||
|
|
||||||
...
|
|
@ -1,41 +0,0 @@
|
|||||||
t = Template(; user=me)
|
|
||||||
pkg_dir = joinpath(t.dir, test_pkg)
|
|
||||||
|
|
||||||
@testset "DroneCI" begin
|
|
||||||
@testset "Plugin creation" begin
|
|
||||||
p = DroneCI()
|
|
||||||
@test isempty(p.gitignore)
|
|
||||||
@test p.src == joinpath(DEFAULTS_DIR, "drone.yml")
|
|
||||||
@test p.dest == ".drone.yml"
|
|
||||||
@test p.badges == [
|
|
||||||
Badge(
|
|
||||||
"Build Status",
|
|
||||||
"https://cloud.drone.io/api/badges/{{USER}}/{{PKGNAME}}.jl/status.svg",
|
|
||||||
"https://cloud.drone.io/{{USER}}/{{PKGNAME}}.jl",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@test isempty(p.view)
|
|
||||||
p = DroneCI(; config_file=nothing)
|
|
||||||
@test p.src === nothing
|
|
||||||
p = DroneCI(; config_file=test_file)
|
|
||||||
@test p.src == test_file
|
|
||||||
@test_throws ArgumentError DroneCI(; config_file=fake_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
@testset "Badge generation" begin
|
|
||||||
p = DroneCI()
|
|
||||||
@test badges(p, me, test_pkg) == ["[](https://cloud.drone.io/$me/$test_pkg.jl)"]
|
|
||||||
end
|
|
||||||
|
|
||||||
@testset "File generation" begin
|
|
||||||
# Without a coverage plugin in the template, there should be no coverage step.
|
|
||||||
p = DroneCI()
|
|
||||||
@test gen_plugin(p, t, test_pkg) == [".drone.yml"]
|
|
||||||
@test isfile(joinpath(pkg_dir, ".drone.yml"))
|
|
||||||
drone = read(joinpath(pkg_dir, ".drone.yml"), String)
|
|
||||||
@test !occursin("coverage_script", drone)
|
|
||||||
rm(joinpath(pkg_dir, ".drone.yml"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
rm(pkg_dir; recursive=true)
|
|
@ -6,7 +6,7 @@
|
|||||||
@test isempty(Template(; disable_defaults=[Git]).user)
|
@test isempty(Template(; disable_defaults=[Git]).user)
|
||||||
end
|
end
|
||||||
mock(PT.default_user => () -> "username") do _du
|
mock(PT.default_user => () -> "username") do _du
|
||||||
@test Template().user == PT.default_user()
|
@test Template().user == "username"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user