ronantakizawa/codereview-bench huggingface dataset:
Repository: caddyserver/caddy
File: caddy.go (Go)

Code before:
	for name, a := range ctx.cfg.apps {
		err := a.Stop()
		if err != nil {
			log.Printf("[ERROR] stop %s: %v", name, err)
		}
	}

	// clean up all modules
	ctx.cfg.cancelFunc()
}

// Validate loads, provisions, and validates
// cfg, but does not start running it.
func Validate(cfg *Config) error {
	_, err := run(cfg, false)
	if err == nil {
		cfg.cancelFunc() // call Cleanup on all modules
	}
	return err
}

// ExportStorage calls List() and Load() on the configured
// storage module and returns the underlying assets. 
func ExportStorage(cfg *Config) (files []struct{
	Name string
	Body []byte
}, err error) {
	ctx, err := run(cfg, false)
	if err != nil {
		return nil, err
	}
	
	defer cfg.cancelFunc()
	stor := ctx.Storage()
	keys, err := stor.List(ctx, "", true)
	if err != nil {
		return nil, err
	}

	for _, k := range keys {
		info, err := stor.Stat(ctx, k)
		if err != nil {
			return nil, err
		}

		if info.IsTerminal {
			v, err := stor.Load(ctx, k)
			if err != nil {
				return nil, err
			}


Review comment (performance):
Loading the entire storage into memory is probably not ideal -- it will blow up for large deployments (where a feature like this is most useful).

Maybe exporting should write directly [to an archive](https://github.com/mholt/archiver).

Although, we're getting into separate tooling territory.

What if, instead, we had a `transfer storage` utility that simply moved the contents of one storage to another storage? We could do it kv-pair by kv-pair, much more efficiently, directly, without any need to read everything into memory or have separate import/export ops.

Code after:
		err := a.Stop()
		if err != nil {
			log.Printf("[ERROR] stop %s: %v", name, err)
		}
	}

	// clean up all modules
	ctx.cfg.cancelFunc()
}

// Validate loads, provisions, and validates
// cfg, but does not start running it.
func Validate(cfg *Config) error {
	_, err := run(cfg, false)
	if err == nil {
		cfg.cancelFunc() // call Cleanup on all modules
	}
	return err
}

// exitProcess exits the process as gracefully as possible,
// but it always exits, even if there are errors doing so.
// It stops all apps, cleans up external locks, removes any
// PID file, and shuts down admin endpoint(s) in a goroutine.
// Errors are logged along the way, and an appropriate exit
// code is emitted.
func exitProcess(ctx context.Context, logger *zap.Logger) {
	// let the rest of the program know we're quitting
	atomic.StoreInt32(exiting, 1)

	// give the OS or service/process manager our 2 weeks' notice: we quit
	if err := notify.Stopping(); err != nil {
		Log().Error("unable to notify service manager of stopping state", zap.Error(err))
	}

	if logger == nil {
		logger = Log()
	}
	logger.Warn("exiting; byeee!! 👋")

	exitCode := ExitCodeSuccess

	// stop all apps
	if err := Stop(); err != nil {
		logger.Error("failed to stop apps", zap.Error(err))
		exitCode = ExitCodeFailedQuit
	}

	// clean up certmagic locks
	certmagic.CleanUpOwnLocks(ctx, logger)
Repository: caddyserver/caddy
File: cmd/commandfuncs.go (Go)

Code before:
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}
	input = caddy.RemoveMetaFields(input)

	var cfg *caddy.Config
	err = caddy.StrictUnmarshalJSON(input, &cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("decoding config: %v", err)
	}

	err = caddy.Validate(cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	fmt.Println("Valid configuration")

	return caddy.ExitCodeSuccess, nil
}

type storVal struct {
	StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
}

func DetermineStorage(configFile string, configAdapter string) (*storVal, error) {
	cfg, _, err := LoadConfig(configFile, configAdapter)
	if err != nil {
		return nil, err
	}

	var tmpStruct storVal
	err = json.Unmarshal(cfg, &tmpStruct)
	if err != nil {
		return nil, fmt.Errorf("unmarshaling storage from config: %v", err)
	}

	return &tmpStruct, nil
}

func cmdImportStorage(fl Flags) (int, error) {
	importStorageCmdConfigFlag := fl.String("config")
	importStorageCmdImportFile := fl.String("input")

	storageCfg, err := DetermineStorage(importStorageCmdConfigFlag, "")
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	// load storage module
	ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})

Review comment (suggestion):
```suggestion
func determineStorage(configFile string, configAdapter string) (*storVal, error) {
```

Code after:
		return caddy.ExitCodeFailedStartup, err
	}
	input = caddy.RemoveMetaFields(input)

	var cfg *caddy.Config
	err = caddy.StrictUnmarshalJSON(input, &cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("decoding config: %v", err)
	}

	err = caddy.Validate(cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	fmt.Println("Valid configuration")

	return caddy.ExitCodeSuccess, nil
}

func cmdFmt(fl Flags) (int, error) {
	formatCmdConfigFile := fl.Arg(0)
	if formatCmdConfigFile == "" {
		formatCmdConfigFile = "Caddyfile"
	}

	// as a special case, read from stdin if the file name is "-"
	if formatCmdConfigFile == "-" {
		input, err := io.ReadAll(os.Stdin)
		if err != nil {
			return caddy.ExitCodeFailedStartup,
				fmt.Errorf("reading stdin: %v", err)
		}
		fmt.Print(string(caddyfile.Format(input)))
		return caddy.ExitCodeSuccess, nil
	}

	input, err := os.ReadFile(formatCmdConfigFile)
	if err != nil {
		return caddy.ExitCodeFailedStartup,
			fmt.Errorf("reading input file: %v", err)
	}

	output := caddyfile.Format(input)

	if fl.Bool("overwrite") {
		if err := os.WriteFile(formatCmdConfigFile, output, 0600); err != nil {
			return caddy.ExitCodeFailedStartup, fmt.Errorf("overwriting formatted file: %v", err)
		}
		return caddy.ExitCodeSuccess, nil
	}
Repository: caddyserver/caddy
File: cmd/commandfuncs.go (Go)

Code before:
		return caddy.ExitCodeFailedStartup, fmt.Errorf("decoding config: %v", err)
	}

	err = caddy.Validate(cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	fmt.Println("Valid configuration")

	return caddy.ExitCodeSuccess, nil
}

type storVal struct {
	StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
}

func DetermineStorage(configFile string, configAdapter string) (*storVal, error) {
	cfg, _, err := LoadConfig(configFile, configAdapter)
	if err != nil {
		return nil, err
	}

	var tmpStruct storVal
	err = json.Unmarshal(cfg, &tmpStruct)
	if err != nil {
		return nil, fmt.Errorf("unmarshaling storage from config: %v", err)
	}

	return &tmpStruct, nil
}

func cmdImportStorage(fl Flags) (int, error) {
	importStorageCmdConfigFlag := fl.String("config")
	importStorageCmdImportFile := fl.String("input")

	storageCfg, err := DetermineStorage(importStorageCmdConfigFlag, "")
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	// load storage module
	ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
	defer cancel()
	val, err := ctx.LoadModule(storageCfg, "StorageRaw")
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}
	stor, err := val.(caddy.StorageConverter).CertMagicStorage()
	if err != nil {
		return caddy.ExitCodeFailedStartup, err

Review comment (suggestion):
This doesn't correctly handle the default case where no storage is defined in the config. My current thought is to check `json.Valid` first so that if `Unmarshal` returns `json.SyntaxError` it should be safe to assume it's the default case.

Code after:
	}

	err = caddy.Validate(cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	fmt.Println("Valid configuration")

	return caddy.ExitCodeSuccess, nil
}

func cmdFmt(fl Flags) (int, error) {
	formatCmdConfigFile := fl.Arg(0)
	if formatCmdConfigFile == "" {
		formatCmdConfigFile = "Caddyfile"
	}

	// as a special case, read from stdin if the file name is "-"
	if formatCmdConfigFile == "-" {
		input, err := io.ReadAll(os.Stdin)
		if err != nil {
			return caddy.ExitCodeFailedStartup,
				fmt.Errorf("reading stdin: %v", err)
		}
		fmt.Print(string(caddyfile.Format(input)))
		return caddy.ExitCodeSuccess, nil
	}

	input, err := os.ReadFile(formatCmdConfigFile)
	if err != nil {
		return caddy.ExitCodeFailedStartup,
			fmt.Errorf("reading input file: %v", err)
	}

	output := caddyfile.Format(input)

	if fl.Bool("overwrite") {
		if err := os.WriteFile(formatCmdConfigFile, output, 0600); err != nil {
			return caddy.ExitCodeFailedStartup, fmt.Errorf("overwriting formatted file: %v", err)
		}
		return caddy.ExitCodeSuccess, nil
	}

	if fl.Bool("diff") {
		diff := difflib.Diff(
			strings.Split(string(input), "\n"),
			strings.Split(string(output), "\n"))
		for _, d := range diff {
			switch d.Delta {
			case difflib.Common:
Repository: caddyserver/caddy
File: cmd/commandfuncs.go (Go)

Code before:
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}
	input = caddy.RemoveMetaFields(input)

	var cfg *caddy.Config
	err = caddy.StrictUnmarshalJSON(input, &cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("decoding config: %v", err)
	}

	err = caddy.Validate(cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	fmt.Println("Valid configuration")

	return caddy.ExitCodeSuccess, nil
}

type storVal struct {
	StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
}

// *storVal should be nil checked even if err == nil
func determineStorage(configFile string, configAdapter string) (*storVal, error) {
	cfg, _, err := LoadConfig(configFile, configAdapter)
	if err != nil {
		return nil, err
	}

	// storage defaults to FileStorage if not explicitly
	// defined in the config, so the config can be valid
	// json but unmarshaling will fail.
	if !json.Valid(cfg) {
		return nil, &json.SyntaxError{}
	}
	var tmpStruct storVal
	err = json.Unmarshal(cfg, &tmpStruct)
	if err != nil {
		// default case, ignore the error
		var jsonError *json.SyntaxError
		if errors.As(err, &jsonError) {
			return nil, nil
		}
		return nil, err
	}

	return &tmpStruct, nil
}

Review comment (suggestion):
```suggestion
// determineStorage returns the top-level storage module from the given config.
// It may return nil even if no error.
```

Code after:
	}
	input = caddy.RemoveMetaFields(input)

	var cfg *caddy.Config
	err = caddy.StrictUnmarshalJSON(input, &cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("decoding config: %v", err)
	}

	err = caddy.Validate(cfg)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

	fmt.Println("Valid configuration")

	return caddy.ExitCodeSuccess, nil
}

func cmdFmt(fl Flags) (int, error) {
	formatCmdConfigFile := fl.Arg(0)
	if formatCmdConfigFile == "" {
		formatCmdConfigFile = "Caddyfile"
	}

	// as a special case, read from stdin if the file name is "-"
	if formatCmdConfigFile == "-" {
		input, err := io.ReadAll(os.Stdin)
		if err != nil {
			return caddy.ExitCodeFailedStartup,
				fmt.Errorf("reading stdin: %v", err)
		}
		fmt.Print(string(caddyfile.Format(input)))
		return caddy.ExitCodeSuccess, nil
	}

	input, err := os.ReadFile(formatCmdConfigFile)
	if err != nil {
		return caddy.ExitCodeFailedStartup,
			fmt.Errorf("reading input file: %v", err)
	}

	output := caddyfile.Format(input)

	if fl.Bool("overwrite") {
		if err := os.WriteFile(formatCmdConfigFile, output, 0600); err != nil {
			return caddy.ExitCodeFailedStartup, fmt.Errorf("overwriting formatted file: %v", err)
		}
		return caddy.ExitCodeSuccess, nil
	}
Repository: caddyserver/caddy
File: modules/caddyhttp/templates/tplcontext.go (Go)

Code before:
// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package templates

import (
	"bytes"
	"fmt"
	"github.com/Masterminds/sprig/v3"
	"github.com/caddyserver/caddy/v2"
	"github.com/dustin/go-humanize"
	"io"
	"io/fs"
	"net"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"sync"
	"text/template"
	"time"

	"github.com/alecthomas/chroma/v2/formatters/html"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
	"github.com/yuin/goldmark"
	highlighting "github.com/yuin/goldmark-highlighting/v2"
	"github.com/yuin/goldmark/extension"
	"github.com/yuin/goldmark/parser"
	gmhtml "github.com/yuin/goldmark/renderer/html"
)

// TemplateContext is the TemplateContext with which HTTP templates are executed.
type TemplateContext struct {
	Root        http.FileSystem
	Req         *http.Request

Review comment (suggestion):
I think your IDE moved these import lines. I don't think it should be done this way, they should be grouped by source, so all stdlib first then github ones together, etc. Running `gofmt -s -w` can fix this up I think.

Code after:
// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package templates

import (
	"bytes"
	"fmt"
	"io"
	"io/fs"
	"net"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"sync"
	"text/template"
	"time"

	"github.com/Masterminds/sprig/v3"
	chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
	"github.com/dustin/go-humanize"
	"github.com/yuin/goldmark"
	highlighting "github.com/yuin/goldmark-highlighting/v2"
	"github.com/yuin/goldmark/extension"
	"github.com/yuin/goldmark/parser"
	gmhtml "github.com/yuin/goldmark/renderer/html"
)

// TemplateContext is the TemplateContext with which HTTP templates are executed.
type TemplateContext struct {
	Root        http.FileSystem
	Req         *http.Request
Repository: caddyserver/caddy
File: modules/caddyhttp/reverseproxy/selectionpolicies.go (Go)

Code before:
			return d.ArgErr()
		}

		for _, weight := range args {
			weightInt, err := strconv.Atoi(weight)
			if err != nil {
				return d.Errf("invalid weight value '%s': %v", weight, err)
			}
			if weightInt < 1 {
				return d.Errf("invalid weight value '%s': weight should be non-zero and positive", weight)
			}
			r.totalWeight += weightInt
			r.Weights = append(r.Weights, weightInt)
		}
	}
	return nil
}

// Provision sets up r.
func (r *WeightedRoundRobinSelection) Provision(ctx caddy.Context) error {
	if len(r.Weights) != 0 {
		r.totalWeight = 0
		for _, weight := range r.Weights {
			r.totalWeight += weight
		}
	}
	return nil
}

// Validate ensures that r's configuration is valid.
func (r WeightedRoundRobinSelection) Validate() error {
	if len(r.Weights) != 0 {
		totalWeight := 0
		for _, weight := range r.Weights {
			totalWeight += weight
		}
		if r.totalWeight != totalWeight {
			return fmt.Errorf("total weight miscalculated")
		}
	}
	return nil
}

// Select returns an available host, if any.
func (r *WeightedRoundRobinSelection) Select(pool UpstreamPool, _ *http.Request, _ http.ResponseWriter) *Upstream {
	if len(pool) == 0 {
		return nil
	}
	if len(r.Weights) < 2 {
		return pool[0]
	}

Review comment (suggestion):
```suggestion
	for _, weight := range r.Weights {
		r.totalWeight += weight
	}
```

0 is the default value anyway, and no iteration will happen if len is 0. Simpler code :)

Code after:
		if len(args) == 0 {
			return d.ArgErr()
		}

		for _, weight := range args {
			weightInt, err := strconv.Atoi(weight)
			if err != nil {
				return d.Errf("invalid weight value '%s': %v", weight, err)
			}
			if weightInt < 1 {
				return d.Errf("invalid weight value '%s': weight should be non-zero and positive", weight)
			}
			r.Weights = append(r.Weights, weightInt)
		}
	}
	return nil
}

// Provision sets up r.
func (r *WeightedRoundRobinSelection) Provision(ctx caddy.Context) error {
	for _, weight := range r.Weights {
		r.totalWeight += weight
	}
	return nil
}

// Select returns an available host, if any.
func (r *WeightedRoundRobinSelection) Select(pool UpstreamPool, _ *http.Request, _ http.ResponseWriter) *Upstream {
	if len(pool) == 0 {
		return nil
	}
	if len(r.Weights) < 2 {
		return pool[0]
	}
	var index, totalWeight int
	currentWeight := int(atomic.AddUint32(&r.index, 1)) % r.totalWeight
	for i, weight := range r.Weights {
		totalWeight += weight
		if currentWeight < totalWeight {
			index = i
			break
		}
	}

	upstreams := make([]*Upstream, 0, len(r.Weights))
	for _, upstream := range pool {
		if !upstream.Available() {
			continue
		}
		upstreams = append(upstreams, upstream)
		if len(upstreams) == cap(upstreams) {
Repository: caddyserver/caddy
File: modules/caddyhttp/reverseproxy/selectionpolicies.go (Go)

Code before:
}

// Validate ensures that r's configuration is valid.
func (r WeightedRoundRobinSelection) Validate() error {
	if len(r.Weights) != 0 {
		totalWeight := 0
		for _, weight := range r.Weights {
			totalWeight += weight
		}
		if r.totalWeight != totalWeight {
			return fmt.Errorf("total weight miscalculated")
		}
	}
	return nil
}

// Select returns an available host, if any.
func (r *WeightedRoundRobinSelection) Select(pool UpstreamPool, _ *http.Request, _ http.ResponseWriter) *Upstream {
	if len(pool) == 0 {
		return nil
	}
	if len(r.Weights) < 2 {
		return pool[0]
	}
	index := 0
	totalWeight := 0
	currentWeight := int(atomic.AddUint32(&r.index, 1)) % r.totalWeight
	for i, weight := range r.Weights {
		totalWeight += weight
		if currentWeight < totalWeight {
			index = i
			break
		}
	}

	upstreams := make([]*Upstream, 0, len(r.Weights))
	for _, upstream := range pool {
		if !upstream.Available() {
			continue
		}
		upstreams = append(upstreams, upstream)
		if len(upstreams) == cap(upstreams) {
			break
		}
	}
	if len(upstreams) == 0 {
		return nil
	}
	return upstreams[index%len(upstreams)]
}


Review comment (suggestion):
```suggestion
	var index, totalWeight int
```

Totally just a style nit, but hear me out :)

Code after:
func (r *WeightedRoundRobinSelection) Select(pool UpstreamPool, _ *http.Request, _ http.ResponseWriter) *Upstream {
	if len(pool) == 0 {
		return nil
	}
	if len(r.Weights) < 2 {
		return pool[0]
	}
	var index, totalWeight int
	currentWeight := int(atomic.AddUint32(&r.index, 1)) % r.totalWeight
	for i, weight := range r.Weights {
		totalWeight += weight
		if currentWeight < totalWeight {
			index = i
			break
		}
	}

	upstreams := make([]*Upstream, 0, len(r.Weights))
	for _, upstream := range pool {
		if !upstream.Available() {
			continue
		}
		upstreams = append(upstreams, upstream)
		if len(upstreams) == cap(upstreams) {
			break
		}
	}
	if len(upstreams) == 0 {
		return nil
	}
	return upstreams[index%len(upstreams)]
}

// RandomChoiceSelection is a policy that selects
// two or more available hosts at random, then
// chooses the one with the least load.
type RandomChoiceSelection struct {
	// The size of the sub-pool created from the larger upstream pool. The default value
	// is 2 and the maximum at selection time is the size of the upstream pool.
	Choose int `json:"choose,omitempty"`
}

// CaddyModule returns the Caddy module information.
func (RandomChoiceSelection) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.reverse_proxy.selection_policies.random_choose",
		New: func() caddy.Module { return new(RandomChoiceSelection) },
	}
}

// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
Repository: caddyserver/caddy
File: cmd/caddy/main.go (Go)

Code before:
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main is the entry point of the Caddy application.
// Most of Caddy's functionality is provided through modules,
// which can be plugged in by adding their import below.
//
// There is no need to modify the Caddy source code to customize your
// builds. You can easily build a custom Caddy with these simple steps:
//
//  1. Copy this file (main.go) into a new folder
//  2. Edit the imports below to include the modules you want plugged in
//  3. Run `go mod init caddy`
//  4. Run `go install` or `go build` - you now have a custom binary!
//
// Or you can use xcaddy which does it all for you as a command:
// https://github.com/caddyserver/xcaddy
package main

import (
	caddycmd "github.com/caddyserver/caddy/v2/cmd"
	// plug in Caddy modules here
	_ "github.com/caddyserver/caddy/v2/modules/standard"
)

func main() {
	caddycmd.Main()
}


Review comment (suggestion):
I don't like this change, the space is intentional here, because this file is meant to be copied and edited by hand (as a manual way of building Caddy with plugins etc)

Code after:
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main is the entry point of the Caddy application.
// Most of Caddy's functionality is provided through modules,
// which can be plugged in by adding their import below.
//
// There is no need to modify the Caddy source code to customize your
// builds. You can easily build a custom Caddy with these simple steps:
//
//  1. Copy this file (main.go) into a new folder
//  2. Edit the imports below to include the modules you want plugged in
//  3. Run `go mod init caddy`
//  4. Run `go install` or `go build` - you now have a custom binary!
//
// Or you can use xcaddy which does it all for you as a command:
// https://github.com/caddyserver/xcaddy
package main

import (
	caddycmd "github.com/caddyserver/caddy/v2/cmd"

	// plug in Caddy modules here
	_ "github.com/caddyserver/caddy/v2/modules/standard"
)

func main() {
	caddycmd.Main()
}