Skip to content

Commit

Permalink
Merge pull request #10 from moul/dev/moul/improve-maintenance
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Apr 25, 2021
2 parents cdcb5c8 + 9b630c2 commit cc3ebae
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 53 deletions.
12 changes: 11 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ func main() {
type Opts struct {
Path string
Maintenance struct {
NoFetch bool
CheckoutMainBranch bool
NoFetch bool
BumpDeps bool
Standard bool
ShowDiff bool
}
Doctor struct{}
Version struct{}
Expand All @@ -34,6 +38,7 @@ var (
doctorFs = flag.NewFlagSet("doctor", flag.ExitOnError)
maintenanceFs = flag.NewFlagSet("maintenance", flag.ExitOnError)
versionFs = flag.NewFlagSet("version", flag.ExitOnError)
bumpDepsFs = flag.NewFlagSet("bump-deps", flag.ExitOnError)
opts Opts

logger *zap.Logger
Expand All @@ -50,7 +55,12 @@ func run(args []string) error {
setupRootFlags(rootFs)
setupRootFlags(doctorFs)
setupRootFlags(maintenanceFs)
setupRootFlags(bumpDepsFs)
maintenanceFs.BoolVar(&opts.Maintenance.CheckoutMainBranch, "checkout-main-branch", true, "switch to the main branch before applying the maintenance")
maintenanceFs.BoolVar(&opts.Maintenance.NoFetch, "no-fetch", false, "do not fetch origin")
maintenanceFs.BoolVar(&opts.Maintenance.BumpDeps, "bump-deps", false, "bump dependencies")
maintenanceFs.BoolVar(&opts.Maintenance.Standard, "std", true, "standard maintenance tasks")
maintenanceFs.BoolVar(&opts.Maintenance.ShowDiff, "show-diff", true, "display git diff of the changes")

// init logger
{
Expand Down
182 changes: 130 additions & 52 deletions maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,46 @@ func doMaintenanceOnce(_ context.Context, path string) error {
}
}

if !project.Git.InMainBranch {
if opts.Maintenance.CheckoutMainBranch && !project.Git.InMainBranch {
logger.Debug("project is not using the main branch",
zap.String("current", project.Git.CurrentBranch),
zap.String("main", project.Git.MainBranch),
)
mainBranch, err := project.Git.repo.Branch(project.Git.MainBranch)
if err != nil {
return fmt.Errorf("failed to get ref for main branch: %q: %w", project.Git.MainBranch, err)
}

// TODO: checkout
// TODO: pull
return fmt.Errorf("not implemented: git checkout master/main")
err = project.Git.workTree.Checkout(&git.CheckoutOptions{
Branch: mainBranch.Merge,
})
if err != nil {
return fmt.Errorf("failed to checkout main branch: %q: %w", project.Git.MainBranch, err)
}

err = project.Git.workTree.Pull(&git.PullOptions{})
switch err {
case git.NoErrAlreadyUpToDate: // skip
case nil: // skip
default:
return fmt.Errorf("failed to pull main branch: %q: %w", project.Git.MainBranch, err)
}
}

// TODO: check if the worktree looks like the corresponding template
// check if the project looks like a one that can be maintained by repoman
{
var errs error
for _, expected := range []string{"Makefile", "rules.mk"} {
if !u.FileExists(filepath.Join(project.Path, expected)) {
errs = multierr.Append(errs, fmt.Errorf("missing file: %q", expected))
}
}
if errs != nil {
return fmt.Errorf("project is not compatible with repoman: %w", errs)
}
}

initMoulBotEnv()

// TODO
// - repoman.yml ->
Expand All @@ -86,73 +114,123 @@ func doMaintenanceOnce(_ context.Context, path string) error {
// - auto update from template
// - open PR / update existing one

script := `
main() {
# renovate.json
mkdir -p .github
git mv renovate.json .github/renovate.json || true
git rm -f renovate.json || true
cp ~/go/src/moul.io/golang-repo-template/.github/renovate.json .github/ || true
git add .github/renovate.json || true
git add renovate.json || true
# dependabot
cp ~/go/src/moul.io/golang-repo-template/.github/dependabot.yml .github/ || true
git add .github/dependabot.yml || true
# rules.mk
if [ -f rules.mk ]; then cp ~/go/src/moul.io/rules.mk/rules.mk .; fi || true
# authors
if [ -f rules.mk ]; then make generate.authors; git add AUTHORS; fi || true
# copyright
set -xe; \
for prefix in "漏" "Copyright" "Copyright (c)"; do \
for file in README.md LICENSE-APACHE LICENSE-MIT LICENSE COPYRIGHT; do \
if [ -f "$file" ]; then \
sed -i "s/$prefix 2014 /$prefix 2014-2021 /" $file; \
sed -i "s/$prefix 2015 /$prefix 2015-2021 /" $file; \
sed -i "s/$prefix 2016 /$prefix 2016-2021 /" $file; \
sed -i "s/$prefix 2017 /$prefix 2017-2021 /" $file; \
sed -i "s/$prefix 2018 /$prefix 2018-2021 /" $file; \
sed -i "s/$prefix 2019 /$prefix 2019-2021 /" $file; \
sed -i "s/$prefix 2020 /$prefix 2020-2021 /" $file; \
sed -i "s/$prefix \([0-9][0-9][0-9][0-9]\)-20[0-9][0-9] /$prefix \1-2021 /" $file; \
sed -i "s/$prefix 2021-2021/$prefix 2021 /" $file; \
fi; \
done; \
done
# golangci-lint fix
sed -i "s/version: v1.26/version: v1.38/" .github/workflows/*.yml || true
sed -i "s/version: v1.27/version: v1.38/" .github/workflows/*.yml || true
sed -i "s/version: v1.28/version: v1.38/" .github/workflows/*.yml || true
if opts.Maintenance.BumpDeps {
logger.Debug("bumping deps", zap.String("project", project.Path))
// TODO: for each dirs with a go.mod, except vendor; overridable by repoman.yml
// TODO: overridable go binary
cmd := exec.Command("go", "get", "-u", "./...")
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
cmd.Dir = project.Path
cmd.Env = os.Environ()
if err := cmd.Run(); err != nil {
return fmt.Errorf("exec failed: %w", err)
}
}

if opts.Maintenance.Standard {
logger.Debug("applying standard changes", zap.String("project", project.Path))
script := `
main() {
# renovate.json
mkdir -p .github
git mv renovate.json .github/renovate.json || true
git rm -f renovate.json || true
cp ~/go/src/moul.io/golang-repo-template/.github/renovate.json .github/ || true
git add .github/renovate.json || true
git add renovate.json || true
# dependabot
cp ~/go/src/moul.io/golang-repo-template/.github/dependabot.yml .github/ || true
git add .github/dependabot.yml || true
# rules.mk
if [ -f rules.mk ]; then cp ~/go/src/moul.io/rules.mk/rules.mk .; fi || true
# authors
if [ -f rules.mk ]; then make generate.authors; git add AUTHORS; fi || true
# copyright
set -xe; \
for prefix in "漏" "Copyright" "Copyright (c)"; do \
for file in README.md LICENSE-APACHE LICENSE-MIT LICENSE COPYRIGHT; do \
if [ -f "$file" ]; then \
sed -i "s/$prefix 2014 /$prefix 2014-2021 /" $file; \
sed -i "s/$prefix 2015 /$prefix 2015-2021 /" $file; \
sed -i "s/$prefix 2016 /$prefix 2016-2021 /" $file; \
sed -i "s/$prefix 2017 /$prefix 2017-2021 /" $file; \
sed -i "s/$prefix 2018 /$prefix 2018-2021 /" $file; \
sed -i "s/$prefix 2019 /$prefix 2019-2021 /" $file; \
sed -i "s/$prefix 2020 /$prefix 2020-2021 /" $file; \
sed -i "s/$prefix \([0-9][0-9][0-9][0-9]\)-20[0-9][0-9] /$prefix \1-2021 /" $file; \
sed -i "s/$prefix 2021-2021/$prefix 2021 /" $file; \
fi; \
done; \
done
# golangci-lint fix
sed -i "s/version: v1.26/version: v1.38/" .github/workflows/*.yml || true
sed -i "s/version: v1.27/version: v1.38/" .github/workflows/*.yml || true
sed -i "s/version: v1.28/version: v1.38/" .github/workflows/*.yml || true
}
main
`
cmd := exec.Command("/bin/sh", "-xec", script)
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
cmd.Dir = project.Path
cmd.Env = os.Environ()

err := cmd.Run()
if err != nil {
return fmt.Errorf("standard script execution failed: %w", err)
}
}

if opts.Maintenance.ShowDiff {
script := `
main() {
# apply changes
git diff
git diff --cached
git status
}
main
`
cmd := exec.Command("/bin/sh", "-xec", script)
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
cmd.Dir = project.Path
cmd.Env = os.Environ()

err := cmd.Run()
if err != nil {
return fmt.Errorf("publish script execution failed: %w", err)
}
}

// open a PR for the changes
{
script := `
main() {
# apply changes
git branch -D dev/moul/maintenance || true
git checkout -b dev/moul/maintenance
git status
git commit -s -a -m "chore: repo maintenance 馃" -m "more details: https://github.com/moul/repoman"
git push -u origin dev/moul/maintenance -f
hub pull-request -m "chore: repo maintenance 馃" -m "more details: https://github.com/moul/repoman" || hub pr list -f "- %pC%>(8)%i%Creset %U - %t% l%n"
}
main
`
// exec
{
cmd := exec.Command("/bin/sh", "-xec", script)
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
cmd.Dir = project.Path
initMoulBotEnv()
cmd.Env = os.Environ()

err := cmd.Run()
if err != nil {
return fmt.Errorf("script execution failed: %w", err)
return fmt.Errorf("publish script execution failed: %w", err)
}
}

Expand Down

0 comments on commit cc3ebae

Please sign in to comment.