Skip to content

Commit cbd52ff

Browse files
author
Anirudh
committed
Add files for setup
1 parent 8c3bda2 commit cbd52ff

7 files changed

Lines changed: 210 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Whitespace-only changes.

‎LICENSE‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2022 anirudh2
3+
Copyright (c) 2022 Anirudh A. Patel
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

‎Project.toml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[deps]
2+
CompatHelper = "aa819f21-2bde-4658-8897-bab36330d9b7"
3+
Git = "d7ba0133-e1db-5d97-8f8c-041e4b3a1eb2"
4+
PkgTemplates = "14b8a8f1-9102-5b29-a752-f990bacb7fe1"

‎README.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
11
# setup-jl
22
An opinionated way to create Julia packages with Semantic Release
3+
4+
Much Credit to Jaan Tollander de Balsch.
5+
I modified much of this from [his work](https://github.com/jaantollander/SemanticReleaseExample.jl).
6+
7+
## Usage
8+
9+
1. Clone this repository.
10+
2. Instantiate the project (download the dependencies) by running `julia --project -e 'import Pkg; Pkg.instantiate()'`
11+
3. Modify *config.toml* to match your preferences.
12+
4. Create an empty repository with the correct path on GitHub.
13+
5. Run the script with `julia --project -e 'include("setup.jl"); createpackage("config.toml")'`. This will populate that empty repo automatically.
14+
6. Follow the instructions in the created README to finish setting the repo up.
15+
16+
That's it!
17+
18+
Make sure to familiarise yourself with [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) as these are how you'll trigger the release pipeline.

‎Release.yml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Release
2+
3+
on:
4+
workflow_run:
5+
workflows: ["CI"]
6+
branches: [main]
7+
types:
8+
- completed
9+
10+
jobs:
11+
release:
12+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
13+
name: Release
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v2
18+
- name: Semantic Release
19+
uses: cycjimmy/semantic-release-action@v2
20+
env:
21+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22+
with:
23+
semantic_version: 18
24+
extra_plugins: |
25+
@semantic-release/changelog
26+
@semantic-release/git
27+
@google/semantic-release-replace-plugin

‎config.toml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name = "New.jl" # This must already be created as an empty repo on github.com/{user}
2+
user = "anirudh2" # github.com/{user}
3+
authors = "Anirudh A. Patel" # Can be ["Author 1", "Author 2"]
4+
julia = [1, 8] # 1.8
5+
dir = "~/projects" # Path where the project is created
6+
license = "MIT" # E.g., ASL is Apache 2.0

‎setup.jl‎

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import Git as G
2+
3+
using PkgTemplates
4+
import PkgTemplates
5+
6+
using TOML
7+
8+
struct SemanticReleaseBadge <: PkgTemplates.BadgePlugin end
9+
10+
"""
11+
Badge for semantic release
12+
"""
13+
function PkgTemplates.badges(::SemanticReleaseBadge)
14+
return PkgTemplates.Badge(
15+
"semantic-release",
16+
"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg",
17+
"https://github.com/semantic-release/semantic-release",
18+
)
19+
end
20+
21+
PkgTemplates.badges(::Documenter{<:PkgTemplates.GitHubPagesStyle}) = [
22+
PkgTemplates.Badge(
23+
"Latest",
24+
"https://img.shields.io/badge/docs-latest-purple.svg",
25+
"https://{{{USER}}}.github.io/{{{PKG}}}.jl/latest/",
26+
),
27+
]
28+
29+
PkgTemplates.badges(::Coveralls) = PkgTemplates.Badge(
30+
"Coverage Status",
31+
"https://img.shields.io/coveralls/github/{{{USER}}}/{{{PKG}}}.jl/badge.svg?branch={{{BRANCH}}}",
32+
"https://coveralls.io/github/{{{USER}}}/{{{PKG}}}.jl?branch={{{BRANCH}}}",
33+
)
34+
35+
"""
36+
createpackage(path::AbstractString)
37+
38+
Create a package with semantic release using the configuration in the TOML file at `path`
39+
40+
Run using `julia -e 'include("setup.jl"); createpackage(path)'`
41+
"""
42+
function createpackage(path::AbstractString)
43+
config = TOML.parsefile(path)
44+
createpackage(;
45+
name=config["name"],
46+
user=config["user"],
47+
authors=config["authors"],
48+
julia=VersionNumber(config["julia"]...),
49+
dir=config["dir"],
50+
license=config["license"]
51+
)
52+
end
53+
54+
"""
55+
createpackage(;name="MyProject.jl", user="anirudh2", authors="Anirudh A. Patel", julia=v"1.8", dir="~/projects/", licensetype="MIT")
56+
57+
Create a package with semantic release.
58+
59+
Run using `julia -e 'include("setup.jl"); createpackage(;kwargs)'`
60+
61+
- `user` is the part of the GitHub URL that comes after github.com. E.g., github.com/anirudh2 => user="anirudh2"
62+
- `license` can be "MIT", "ASL" (Apache 2), "GPL", etc. A full list is available on [github](https://github.com/JuliaCI/PkgTemplates.jl/tree/master/templates/licenses)
63+
"""
64+
function createpackage(; name, user, authors, julia, dir, license)
65+
@info "Creating Package"
66+
t = PkgTemplates.Template(;
67+
user=user,
68+
authors=authors,
69+
julia=julia,
70+
dir="~/projects/",
71+
plugins=[
72+
Git(; gpgsign=true, ssh=true),
73+
GitHubActions(; extra_versions=String[], coverage=true),
74+
Coveralls(),
75+
Documenter{PkgTemplates.GitHubActions}(),
76+
BlueStyleBadge(),
77+
Citation(),
78+
License(; name=license),
79+
Tests(; project=true),
80+
SrcDir(),
81+
ProjectFile(),
82+
SemanticReleaseBadge(),
83+
CompatHelper(),
84+
!TagBot,
85+
])
86+
t(name)
87+
88+
@info "Copying Relevant Files To Package Repo"
89+
namesplit = name |> splitext |> first
90+
fulldir = dir |> expanduser |> realpath
91+
path = joinpath(fulldir, namesplit)
92+
cp("Release.yml", joinpath(path, ".github", "workflows", "Release.yml"))
93+
cp(".releaserc", joinpath(path, ".releaserc"))
94+
cp("CHANGELOG.md", joinpath(path, "CHANGELOG.md"))
95+
96+
@info "Correcting initial version"
97+
tomlpath = joinpath(path, "Project.toml")
98+
modfile(tomlpath, x -> x == "version = \"0.1.0\"\n", "version = \"0.0.0\"\n")
99+
100+
@info "Setting correct devurl for Documentation"
101+
makedocpath = joinpath(path, "docs", "make.jl")
102+
# \t is 8 spaces, so just use 4 spaces manually
103+
modfile(makedocpath, x -> contains(x, "devbranch"), " devbranch=\"main\",\n devurl=\"latest\",\n")
104+
105+
@info "Setting git repo for semantic release"
106+
releasercpath = joinpath(path, ".releaserc")
107+
modfile(releasercpath, x -> contains(x, "repositoryUrl"), " \"repositoryUrl\": \"git@github.com:$user/$name.git\"")
108+
109+
@info "Setting up coveralls"
110+
ciymlpath = joinpath(path, ".github", "workflows", "CI.yml")
111+
modfile(ciymlpath, x -> contains(x, "julia-runtest"), " - uses: julia-actions/julia-runtest@v1\n - uses: julia-actions/julia-processcoverage@v1\n")
112+
modfile(ciymlpath, x -> contains(x, "COVERALLS_TOKEN"), " COVERALLS_TOKEN: \${{ secrets.GITHUB_TOKEN }}\n")
113+
114+
@info "Appending post-setup instructions to README"
115+
open(joinpath(path, "README.md"), "a") do io
116+
lines = [
117+
"\n## TODO\n",
118+
"\n I generally recommend doing step 1 running this script, but it's not a big deal if you do it after.\n",
119+
"\n1. Go to [Coveralls](https://coveralls.io/) and activate this repo.",
120+
"\n2. Once CI finishes running for the first time, go to Settings, Pages, and select the branch `gh-pages`",
121+
"\n3. Once you've done these things, delete this TODO section and commit the change with the message `chore: finished repo setup`"
122+
]
123+
for line in lines
124+
write(io, line)
125+
end
126+
end
127+
128+
@info "Creating initial commit and tag"
129+
@warn "This will fail if you have not created the upstream repo on GitHub at the correct URL."
130+
@warn "You must also have gpg commit signing set up."
131+
cd(path)
132+
run(`$(G.git()) add .`)
133+
run(`$(G.git()) commit -m "chore: Set up project"`)
134+
run(`$(G.git()) tag v0.0.0 -m "Set up project"`)
135+
run(`$(G.git()) push --set-upstream origin main v0.0.0`)
136+
end
137+
138+
"""
139+
Modify the file at `path` at lines that match `predicate`, replacing the lines with
140+
`replacement`
141+
"""
142+
function modfile(path::String, predicate::F, replacement::String) where {F<:Function}
143+
# https://stackoverflow.com/questions/58013970/how-to-edit-a-line-of-a-file-in-julia
144+
(tmppath, tmpio) = mktemp()
145+
open(path) do io
146+
for line in eachline(io; keep=true)
147+
if predicate(line)
148+
line = replacement
149+
end
150+
write(tmpio, line)
151+
end
152+
end
153+
close(tmpio)
154+
mv(tmppath, path, force=true)
155+
return nothing
156+
end

0 commit comments

Comments
 (0)