2021-09-29 15:38:50 +00:00
|
|
|
package build
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2023-01-29 10:54:56 +00:00
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
2023-02-23 17:49:45 +00:00
|
|
|
"gh.tarampamp.am/error-pages/internal/cli/shared"
|
|
|
|
"gh.tarampamp.am/error-pages/internal/config"
|
|
|
|
"gh.tarampamp.am/error-pages/internal/tpl"
|
2021-09-29 15:38:50 +00:00
|
|
|
)
|
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
type command struct {
|
|
|
|
c *cli.Command
|
|
|
|
}
|
|
|
|
|
2021-09-29 15:38:50 +00:00
|
|
|
// NewCommand creates `build` command.
|
2023-01-29 10:54:56 +00:00
|
|
|
func NewCommand(log *zap.Logger) *cli.Command {
|
|
|
|
var cmd = command{}
|
|
|
|
|
|
|
|
const (
|
|
|
|
generateIndexFlagName = "index"
|
|
|
|
disableL10nFlagName = "disable-l10n"
|
2021-09-29 15:38:50 +00:00
|
|
|
)
|
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
cmd.c = &cli.Command{
|
|
|
|
Name: "build",
|
|
|
|
Aliases: []string{"b"},
|
|
|
|
Usage: "build <output-directory>",
|
|
|
|
Description: "Build the error pages",
|
|
|
|
Action: func(c *cli.Context) error {
|
|
|
|
cfg, cfgErr := config.FromYamlFile(c.String(shared.ConfigFileFlag.Name))
|
|
|
|
if cfgErr != nil {
|
|
|
|
return cfgErr
|
2021-09-29 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
if c.Args().Len() != 1 {
|
2021-09-29 15:38:50 +00:00
|
|
|
return errors.New("wrong arguments count")
|
|
|
|
}
|
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
return cmd.Run(log, cfg, c.Args().First(), c.Bool(generateIndexFlagName), c.Bool(disableL10nFlagName))
|
|
|
|
},
|
|
|
|
Flags: []cli.Flag{ // global flags
|
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: generateIndexFlagName,
|
|
|
|
Aliases: []string{"i"},
|
|
|
|
Usage: "generate index page",
|
|
|
|
},
|
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: disableL10nFlagName,
|
|
|
|
Usage: "disable error pages localization",
|
|
|
|
},
|
|
|
|
shared.ConfigFileFlag,
|
2022-01-27 12:29:49 +00:00
|
|
|
},
|
|
|
|
}
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
return cmd.c
|
2022-01-27 12:29:49 +00:00
|
|
|
}
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
const (
|
|
|
|
outHTMLFileExt = ".html"
|
|
|
|
outIndexFileName = "index"
|
|
|
|
outFilePerm = os.FileMode(0664)
|
|
|
|
outDirPerm = os.FileMode(0775)
|
|
|
|
)
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
func (cmd *command) Run(log *zap.Logger, cfg *config.Config, outDirectoryPath string, generateIndex, disableL10n bool) error { //nolint:funlen,lll
|
2022-01-27 12:29:49 +00:00
|
|
|
if len(cfg.Templates) == 0 {
|
|
|
|
return errors.New("no loaded templates")
|
|
|
|
}
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
log.Info("output directory preparing", zap.String("path", outDirectoryPath))
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
if err := cmd.createDirectory(outDirectoryPath, outDirPerm); err != nil {
|
2022-01-27 12:29:49 +00:00
|
|
|
return errors.Wrap(err, "cannot prepare output directory")
|
|
|
|
}
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-31 08:43:40 +00:00
|
|
|
history, renderer := newBuildingHistory(), tpl.NewTemplateRenderer()
|
|
|
|
defer func() { _ = renderer.Close() }()
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
for _, template := range cfg.Templates {
|
|
|
|
log.Debug("template processing", zap.String("name", template.Name()))
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
for _, page := range cfg.Pages {
|
2023-01-29 10:54:56 +00:00
|
|
|
if err := cmd.createDirectory(path.Join(outDirectoryPath, template.Name()), outDirPerm); err != nil {
|
2021-10-06 17:38:00 +00:00
|
|
|
return err
|
2021-09-29 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
var (
|
|
|
|
fileName = page.Code() + outHTMLFileExt
|
|
|
|
filePath = path.Join(outDirectoryPath, template.Name(), fileName)
|
|
|
|
)
|
|
|
|
|
2022-01-31 08:43:40 +00:00
|
|
|
content, renderingErr := renderer.Render(template.Content(), tpl.Properties{
|
2022-01-27 12:29:49 +00:00
|
|
|
Code: page.Code(),
|
|
|
|
Message: page.Message(),
|
|
|
|
Description: page.Description(),
|
|
|
|
ShowRequestDetails: false,
|
2022-04-12 10:34:35 +00:00
|
|
|
L10nDisabled: disableL10n,
|
2022-01-27 12:29:49 +00:00
|
|
|
})
|
|
|
|
if renderingErr != nil {
|
|
|
|
return renderingErr
|
|
|
|
}
|
2021-10-15 06:06:10 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
if err := os.WriteFile(filePath, content, outFilePerm); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
log.Debug("page rendered", zap.String("path", filePath))
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
if generateIndex {
|
|
|
|
history.Append(
|
|
|
|
template.Name(),
|
|
|
|
page.Code(),
|
|
|
|
page.Message(),
|
|
|
|
path.Join(template.Name(), fileName),
|
|
|
|
)
|
2021-09-29 15:38:50 +00:00
|
|
|
}
|
2022-01-27 12:29:49 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
if generateIndex {
|
|
|
|
var filepath = path.Join(outDirectoryPath, outIndexFileName+outHTMLFileExt)
|
|
|
|
|
|
|
|
log.Info("index file generation", zap.String("path", filepath))
|
|
|
|
|
|
|
|
if err := history.WriteIndexFile(filepath, outFilePerm); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-09-29 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
log.Info("job is done")
|
2021-09-29 15:38:50 +00:00
|
|
|
|
2022-01-27 12:29:49 +00:00
|
|
|
return nil
|
2021-09-29 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2023-01-29 10:54:56 +00:00
|
|
|
func (cmd *command) createDirectory(path string, perm os.FileMode) error {
|
2021-09-29 15:38:50 +00:00
|
|
|
stat, err := os.Stat(path)
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
2022-01-27 12:29:49 +00:00
|
|
|
return os.MkdirAll(path, perm)
|
2021-09-29 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !stat.IsDir() {
|
|
|
|
return errors.New("is not a directory")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|