Skip to content

Commit

Permalink
(puppetlabsGH-1871) Don't infer project name from directory name
Browse files Browse the repository at this point in the history
Previously, we would infer the project name from the directory name if
no name was specified in the bolt-project.yaml. This behavior proved to
be confusing for users, so we now require `name` to be specified
in bolt-project.yaml and otherwise will warn and not load project
content.

We previously recognized `<author>-<name>` directory names as valid
project names (using only the `<name>` portion) as that is a common
repo naming scheme for modules. As the project name must now be
specified explicitly, we instead require it be simply the name portion.

!deprecation

  * **Project names must be explicitly specified** ([puppetlabs#1871](puppetlabs#1871))

    Proejct names must now be specified in `bolt-project.yaml` in order
    for project-level content to be loaded, rather than the name being
    inferred by the name of the project directory.
  • Loading branch information
nicklewis committed Jun 18, 2020
1 parent 5e400ce commit 5697f54
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 53 deletions.
8 changes: 4 additions & 4 deletions documentation/bolt_running_plans.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ path. By default, Bolt looks for downloaded module plans in
`<PROJECT_NAME>/modules/plans/` and local plans in
`<PROJECT_NAME>/site-modules/plans/`.

Using a Bolt project, you can create an empty `<PROJECT_NAME>/bolt-project.yaml`
file, develop your plan in `<PROJECT_NAME>/plans/`, and run Bolt from the root
of your Bolt project directory to test the plan.
Using a Bolt project, you can create a `<PROJECT_NAME>/bolt-project.yaml` file,
develop your plan in `<PROJECT_NAME>/plans/`, and run Bolt from the root of
your Bolt project directory to test the plan.

> **Note**: The `bolt-project.yaml` file is part of an experimental feature. For
> more information, see [Bolt
Expand Down Expand Up @@ -87,4 +87,4 @@ bolt plan run mymodule::myplan --targets app1.myorg.com --params $(@{load_balanc
tasks](./bolt_running_tasks.md).
- To find out how to write your own plan, see [Writing plans in
YAML](./writing_yaml_plans.md) or [Writing plans in the Puppet
language](./writing_plans.md).
language](./writing_plans.md).
6 changes: 3 additions & 3 deletions documentation/bolt_running_tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ directory>/site-modules]`.

The current [Bolt project](./experimental_features.md#bolt-projects) is loaded
as a standalone module at the front of the module path. If you are developing a
new task, you can create an empty `<PROJECT_NAME>/bolt-project.yaml` file,
develop your task in `<PROJECT_NAME>/tasks/`, and run Bolt from the root of your
Bolt project directory to test the task.
new task, you can create a `<PROJECT_NAME>/bolt-project.yaml` file, develop
your task in `<PROJECT_NAME>/tasks/`, and run Bolt from the root of your Bolt
project directory to test the task.

> **Note:** The `bolt-project.yaml` file is part of an experimental feature. For
> more information, see [Bolt
Expand Down
5 changes: 2 additions & 3 deletions documentation/experimental_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,8 @@ log:
#### Naming your project
If you want to set a name for your project that is different from the name of
the Bolt project directory, add a `name` key to `bolt-project.yaml` with the
project name.
The project must have a name in order to load content. To set the project name,
add a `name` key to `bolt-project.yaml` with the project name.

For example:
```yaml
Expand Down
7 changes: 3 additions & 4 deletions documentation/module_structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ module directories on the module path.

By default, the module path includes the `modules` and `site-modules`
directories in the [Bolt project directory](bolt_project_directories.md#). If
`bolt-project.yaml` exists at the root of the project directory, the project
itself is also loaded as a module and namespaced to either `name` in
`bolt-project.yaml` if it's set, or the name of the directory if `name` is not
set.
`bolt-project.yaml` exists at the root of the project directory and contains a
`name` key, the project itself is also loaded as a module and namespaced to the
value of `name`.

> **Note:** The `bolt-project.yaml` file is part of an experimental feature. For
> more information, see [Bolt
Expand Down
3 changes: 1 addition & 2 deletions lib/bolt/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -771,14 +771,13 @@ def install_puppetfile(config, puppetfile, modulepath)
end

def pal
project = config.project.project_file? ? config.project : nil
@pal ||= Bolt::PAL.new(config.modulepath,
config.hiera_config,
config.project.resource_types,
config.compile_concurrency,
config.trusted_external,
config.apply_settings,
project)
config.project)
end

def convert_plan(plan)
Expand Down
4 changes: 3 additions & 1 deletion lib/bolt/pal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ def in_bolt_compiler
# TODO: If we always call this inside a bolt_executor we can remove this here
setup
r = Puppet::Pal.in_tmp_environment('bolt', modulepath: @modulepath, facts: {}) do |pal|
Puppet.override(bolt_project: @project,
# Only load the project if it a) exists, b) has a name it can be loaded with
bolt_project = @project if @project&.name
Puppet.override(bolt_project: bolt_project,
yaml_plan_instantiator: Bolt::PAL::YamlPlan::Loader) do
pal.with_script_compiler do |compiler|
alias_types(compiler)
Expand Down
47 changes: 14 additions & 33 deletions lib/bolt/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,7 @@ def project_file?
end

def name
# If the project is in mymod/Boltdir/bolt-project.yaml, use mymod as the project name
dirname = @path.basename.to_s == 'Boltdir' ? @path.parent.basename.to_s : @path.basename.to_s
pname = @data['name'] || dirname
pname.include?('-') ? pname.split('-', 2)[1] : pname
@data['name']
end

def tasks
Expand All @@ -130,36 +127,20 @@ def plans
@data['plans']
end

def project_directory_name?(name)
# it must match an installed project name according to forge validator
name =~ /^[a-z][a-z0-9_]*$/
end

def project_namespaced_name?(name)
# it must match the full project name according to forge validator
name =~ /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/
end

def validate
n = @data['name']
if n && !project_directory_name?(n) && !project_namespaced_name?(n)
raise Bolt::ValidationError, <<~ERROR_STRING
Invalid project name '#{n}' in bolt-project.yaml; project names must match either:
An installed project name (ex. projectname) matching the expression /^[a-z][a-z0-9_]*$/ -or-
A namespaced project name (ex. author-projectname) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/
ERROR_STRING
elsif !project_directory_name?(name) && !project_namespaced_name?(name)
raise Bolt::ValidationError, <<~ERROR_STRING
Invalid project name '#{name}'; project names must match either:
A project name (ex. projectname) matching the expression /^[a-z][a-z0-9_]*$/ -or-
A namespaced project name (ex. author-projectname) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/
Configure project name in <project_dir>/bolt-project.yaml
ERROR_STRING
# If the project name is the same as one of the built-in modules raise a warning
elsif Dir.children(Bolt::PAL::BOLTLIB_PATH).include?(name)
raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\
"with a built-in Bolt module of the same name."
if name
name_regex = /^[a-z][a-z0-9_]*$/
if name !~ name_regex
raise Bolt::ValidationError, <<~ERROR_STRING
Invalid project name '#{name}' in bolt-project.yaml; project name must match #{name_regex.inspect}
ERROR_STRING
elsif Dir.children(Bolt::PAL::BOLTLIB_PATH).include?(name)
raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\
"with a built-in Bolt module of the same name."
end
else
message = "No project name is specified in bolt-project.yaml. Project-level content will not be available."
@warnings << { msg: message }
end

%w[tasks plans].each do |conf|
Expand Down
6 changes: 3 additions & 3 deletions spec/bolt/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@
describe "with namespaced project names" do
let(:config) { { 'name' => 'puppetlabs-foo' } }

it "strips namespace and hyphen" do
project = Bolt::Project.new(config, pwd)
expect(project.name).to eq('foo')
it "raises an error" do
expect { Bolt::Project.new(config, pwd).validate }
.to raise_error(/Invalid project name 'puppetlabs-foo' in bolt-project.yaml/)
end
end
end
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/projects/embedded/Boltdir/bolt-project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name: embedded
1 change: 1 addition & 0 deletions spec/fixtures/projects/local/bolt-project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name: local

0 comments on commit 5697f54

Please sign in to comment.