Coverage for src/lektor_ng/cli/build.py: 0%
50 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-30 13:49 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-30 13:49 +0000
1# pylint: disable=import-outside-toplevel
2import os
3import sys
4from itertools import chain
5from pathlib import Path
6from lektor_ng.project import Project
7from lektor_ng import cli_utils
8import click
10from lektor_ng.cli_utils import (
11 ResolvedPath,
12)
13from lektor_ng.version import get_version
16def add_options(fn):
17 fn = click.argument(
18 "project_path",
19 type=lambda p: Path(p).expanduser().resolve(),
20 )(fn)
22 fn = click.version_option(prog_name="Lektor", version=get_version())(fn)
24 fn = click.option(
25 "-v",
26 "--verbose",
27 "verbosity",
28 count=True,
29 help="Increases the verbosity of the logging.",
30 )(fn)
32 fn = cli_utils.extraflag(fn)
34 fn = click.option(
35 "--buildstate-path",
36 type=click.Path(writable=True, file_okay=False),
37 default=None,
38 help="Path to a directory that Lektor will use for coordinating "
39 "the state of the build. Defaults to a directory named "
40 "`.lektor` inside the output path.",
41 )(fn)
43 fn = click.option(
44 "--source-info-only",
45 is_flag=True,
46 help="Instead of building only updates the source infos. The "
47 "source info is used by the web admin panel to quickly find "
48 "information about the source files (for instance jump to "
49 "files).",
50 )(fn)
52 fn = cli_utils.pruneflag(fn)
54 fn = click.option(
55 "--watch",
56 is_flag=True,
57 help="If this is enabled the build "
58 "process goes into an automatic loop where it watches the "
59 "file system for changes and rebuilds.",
60 )(fn)
62 fn = click.option(
63 "-O",
64 "--output-path",
65 type=ResolvedPath(writable=True, file_okay=False),
66 default=None,
67 help="The output path.",
68 )(fn)
70 return fn
73# TypeError: main() missing 7 required positional arguments: 'output_path', 'watch', 'prune', 'verbosity', 'source_info_only', 'buildstate_path', and 'extra_flags'
74@click.command()
75@add_options
76def main(
77 output_path,
78 watch,
79 prune,
80 verbosity,
81 source_info_only,
82 buildstate_path,
83 extra_flags,
84 project_path,
85):
86 """Builds the entire project into the final artifacts.
88 The default behavior is to build the project into the default build
89 output path which can be discovered with the `project-info` command
90 but an alternative output folder can be provided with the `--output-path`
91 option.
93 The default behavior is to perform a build followed by a pruning step
94 which removes no longer referenced artifacts from the output folder.
95 Lektor will only build the files that require rebuilding if the output
96 folder is reused.
98 To enforce a clean build you have to issue a `clean` command first.
100 If the build fails the exit code will be `1` otherwise `0`. This can be
101 used by external scripts to only deploy on successful build for instance.
102 """
103 from lektor_ng.builder import Builder
104 from lektor_ng.reporter import CliReporter
106 project = Project.from_path2(project_path)
108 output_path = output_path or os.getenv("LEKTOR_BUILD_OUTPUT_PATH") or project.get_output_path()
110 from lektor_ng.environment import Environment
112 env = Environment(project, load_plugins=False)
114 # TODO re-instate load_plugins
115 from ..pluginsystem import initialize_plugins
117 initialize_plugins(env)
119 with CliReporter(env, verbosity=verbosity):
120 builds = ["first"]
121 if watch:
122 from lektor_ng.watcher import watch_project
124 click.secho("Watching for file system changes", fg="cyan")
125 builds = chain(builds, watch_project(env, output_path, raise_interrupt=False))
127 success = False
128 for _ in builds:
129 builder = Builder(
130 env.new_pad(),
131 output_path,
132 buildstate_path=buildstate_path,
133 extra_flags=extra_flags,
134 )
135 if source_info_only:
136 builder.update_all_source_infos()
137 success = True
138 else:
139 failures = builder.build_all()
140 if prune:
141 builder.prune()
142 success = failures == 0
144 return sys.exit(0 if success else 1)
147if __name__ == "__main__":
148 main()