docopslab-dev 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.adoc +682 -324
- data/docopslab-dev.gemspec +3 -4
- data/lib/docopslab/dev/cast_ops.rb +199 -0
- data/lib/docopslab/dev/config_manager.rb +6 -6
- data/lib/docopslab/dev/data_utils.rb +42 -0
- data/lib/docopslab/dev/docker_aware.rb +40 -0
- data/lib/docopslab/dev/file_utils.rb +18 -7
- data/lib/docopslab/dev/git_branch.rb +201 -0
- data/lib/docopslab/dev/git_hooks.rb +17 -11
- data/lib/docopslab/dev/initializer.rb +34 -11
- data/lib/docopslab/dev/library/cache.rb +167 -0
- data/lib/docopslab/dev/library/fetch.rb +209 -0
- data/lib/docopslab/dev/library.rb +341 -0
- data/lib/docopslab/dev/linters.rb +73 -15
- data/lib/docopslab/dev/manifest.rb +28 -0
- data/lib/docopslab/dev/paths.rb +0 -17
- data/lib/docopslab/dev/script_manager.rb +12 -6
- data/lib/docopslab/dev/skim.rb +109 -0
- data/lib/docopslab/dev/spell_check.rb +2 -2
- data/lib/docopslab/dev/sync_ops.rb +94 -33
- data/lib/docopslab/dev/tasks.rb +58 -18
- data/lib/docopslab/dev/version.rb +1 -1
- data/lib/docopslab/dev.rb +77 -36
- data/specs/data/default-manifest.yml +23 -5
- data/specs/data/library-index.yml +22 -0
- data/specs/data/manifest-schema.yaml +142 -4
- data/specs/data/tasks-def.yml +122 -10
- metadata +28 -73
- data/assets/config-packs/actionlint/base.yml +0 -13
- data/assets/config-packs/actionlint/project.yml +0 -13
- data/assets/config-packs/htmlproofer/base.yml +0 -27
- data/assets/config-packs/htmlproofer/project.yml +0 -25
- data/assets/config-packs/rubocop/base.yml +0 -130
- data/assets/config-packs/rubocop/project.yml +0 -8
- data/assets/config-packs/shellcheck/base.shellcheckrc +0 -14
- data/assets/config-packs/subtxt/ai-asciidoc-antipatterns.sub.txt +0 -11
- data/assets/config-packs/vale/asciidoc/ExplicitSectionIDs.yml +0 -8
- data/assets/config-packs/vale/asciidoc/ExtraLineBeforeLevel1.yml +0 -7
- data/assets/config-packs/vale/asciidoc/OneSentencePerLine.yml +0 -8
- data/assets/config-packs/vale/asciidoc/PreferSourceBlocks.yml +0 -8
- data/assets/config-packs/vale/asciidoc/ProperAdmonitions.yml +0 -8
- data/assets/config-packs/vale/asciidoc/ProperDLs.yml +0 -7
- data/assets/config-packs/vale/asciidoc/UncleanListStart.yml +0 -8
- data/assets/config-packs/vale/authoring/ButParagraph.yml +0 -8
- data/assets/config-packs/vale/authoring/ExNotEg.yml +0 -8
- data/assets/config-packs/vale/authoring/LiteralTerms.yml +0 -20
- data/assets/config-packs/vale/authoring/Spelling.yml +0 -679
- data/assets/config-packs/vale/base.ini +0 -38
- data/assets/config-packs/vale/config/scripts/ExplicitSectionIDs.tengo +0 -56
- data/assets/config-packs/vale/config/scripts/ExtraLineBeforeLevel1.tengo +0 -121
- data/assets/config-packs/vale/config/scripts/OneSentencePerLine.tengo +0 -53
- data/assets/config-packs/vale/project.ini +0 -5
- data/assets/hooks/pre-commit +0 -63
- data/assets/hooks/pre-push +0 -72
- data/assets/scripts/adoc_section_ids.rb +0 -50
- data/assets/scripts/build-common.sh +0 -193
- data/assets/scripts/build-docker.sh +0 -64
- data/assets/scripts/build.sh +0 -56
- data/assets/scripts/parse_jekyll_asciidoc_logs.rb +0 -467
- data/assets/templates/Gemfile +0 -7
- data/assets/templates/Rakefile +0 -3
- data/assets/templates/gitignore +0 -69
- data/assets/templates/jekyll-asciidoc-fix.prompt.yml +0 -17
- data/assets/templates/spellcheck.prompt.yml +0 -16
- data/docs/agent/AGENTS.md +0 -229
- data/docs/agent/index.md +0 -80
- data/docs/agent/missions/conduct-release.md +0 -224
- data/docs/agent/missions/setup-new-project.md +0 -250
- data/docs/agent/roles/devops-release-engineer.md +0 -152
- data/docs/agent/roles/docops-engineer.md +0 -193
- data/docs/agent/roles/planner-architect.md +0 -74
- data/docs/agent/roles/product-engineer.md +0 -153
- data/docs/agent/roles/product-manager.md +0 -130
- data/docs/agent/roles/project-manager.md +0 -139
- data/docs/agent/roles/qa-testing-engineer.md +0 -115
- data/docs/agent/roles/tech-docs-manager.md +0 -143
- data/docs/agent/roles/tech-writer.md +0 -163
- data/docs/agent/skills/asciidoc.md +0 -609
- data/docs/agent/skills/code-commenting.md +0 -347
- data/docs/agent/skills/fix-broken-links.md +0 -309
- data/docs/agent/skills/fix-jekyll-asciidoc-build-errors.md +0 -23
- data/docs/agent/skills/fix-spelling-issues.md +0 -13
- data/docs/agent/skills/git.md +0 -170
- data/docs/agent/skills/github-issues.md +0 -135
- data/docs/agent/skills/product-release-rollback-and-patching.md +0 -71
- data/docs/agent/skills/rake-cli-dev.md +0 -57
- data/docs/agent/skills/readme-driven-dev.md +0 -13
- data/docs/agent/skills/release-history.md +0 -29
- data/docs/agent/skills/ruby.md +0 -192
- data/docs/agent/skills/schemagraphy-sgyml.md +0 -18
- data/docs/agent/skills/tests-running.md +0 -25
- data/docs/agent/skills/tests-writing.md +0 -45
- data/docs/agent/skills/write-the-docs.md +0 -54
- data/docs/agent/topics/common-project-paths.md +0 -117
- data/docs/agent/topics/dev-tooling-usage.md +0 -202
- data/docs/agent/topics/devops-ci-cd.md +0 -55
- data/docs/agent/topics/product-docs-deployment.md +0 -25
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'asciisourcerer'
|
|
5
|
+
require 'sourcerer/util/pathifier'
|
|
6
|
+
|
|
7
|
+
module DocOpsLab
|
|
8
|
+
module Dev
|
|
9
|
+
# Source skimming via Sourcerer::SourceSkim
|
|
10
|
+
module Skim
|
|
11
|
+
ADOC_EXTS = %w[.adoc .asc .ad .asciidoc].freeze
|
|
12
|
+
MD_EXTS = %w[.md .markdown].freeze
|
|
13
|
+
ALL_EXTS = (ADOC_EXTS + MD_EXTS).freeze
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
# Skim all supported file types (AsciiDoc + Markdown), format auto-detected.
|
|
17
|
+
def run path, form: nil, syntax: nil
|
|
18
|
+
run_with_format(path, exts: ALL_EXTS, form: form, syntax: syntax)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Skim AsciiDoc source files only.
|
|
22
|
+
def run_adoc path, form: nil, syntax: nil
|
|
23
|
+
run_with_format(path, exts: ADOC_EXTS, form: form, syntax: syntax, default_forms: [:tree])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Skim Markdown source files only, with optional upstream:local overlay support.
|
|
27
|
+
def run_md path, form: nil, syntax: nil
|
|
28
|
+
run_with_format(path, exts: MD_EXTS, form: form, syntax: syntax, overlay: true)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def run_with_format path, exts:, form: nil, syntax: nil, default_forms: nil, overlay: false
|
|
34
|
+
unless path
|
|
35
|
+
puts '❌ Path is required.'
|
|
36
|
+
puts 'Usage: bundle exec rake labdev:skim[path,form,syntax]'
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
forms = form ? parse_forms(form) : default_forms
|
|
41
|
+
file_paths = overlay ? resolve_overlay_paths(path, exts) : resolve_paths(path, exts)
|
|
42
|
+
|
|
43
|
+
if file_paths.empty?
|
|
44
|
+
ext_desc = exts.size == 1 ? exts.first : exts.join(', ')
|
|
45
|
+
warn "No #{ext_desc} files found for: #{path}"
|
|
46
|
+
return
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
results = {}
|
|
50
|
+
cats = Sourcerer::SourceSkim::DEFAULT_CATEGORIES - [:attributes_custom]
|
|
51
|
+
file_paths.each do |fp|
|
|
52
|
+
skim_opts = { categories: cats }
|
|
53
|
+
skim_opts[:forms] = forms if forms
|
|
54
|
+
results[fp] = Sourcerer::SourceSkim.skim_file(fp, **skim_opts)
|
|
55
|
+
end
|
|
56
|
+
portable = JSON.parse(JSON.generate(results))
|
|
57
|
+
|
|
58
|
+
output_syntax = resolve_syntax(syntax, form)
|
|
59
|
+
puts output_syntax == :json ? JSON.pretty_generate(portable) : portable.to_yaml
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Resolve file paths with optional upstream:local overlay.
|
|
63
|
+
#
|
|
64
|
+
# When path_arg contains ':', split into upstream_dir:local_dir. Local files shadow
|
|
65
|
+
# upstream files that share the same relative path; local-only files are appended.
|
|
66
|
+
def resolve_overlay_paths path_arg, exts
|
|
67
|
+
parts = path_arg.split(':', 2).map(&:strip)
|
|
68
|
+
return resolve_paths(parts[0], exts) if parts.size == 1
|
|
69
|
+
|
|
70
|
+
upstream_dir, local_dir = parts
|
|
71
|
+
upstream_map = build_relative_map(upstream_dir, exts)
|
|
72
|
+
local_map = build_relative_map(local_dir, exts)
|
|
73
|
+
upstream_map.merge(local_map).values
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def build_relative_map dir_path, exts
|
|
77
|
+
dir_path = dir_path.chomp('/')
|
|
78
|
+
return {} unless File.directory?(dir_path)
|
|
79
|
+
|
|
80
|
+
abs_base = File.expand_path(dir_path)
|
|
81
|
+
Sourcerer::Util::Pathifier.match(dir_path).enum
|
|
82
|
+
.select { |p| exts.any? { |e| p.end_with?(e) } }
|
|
83
|
+
.each_with_object({}) do |abs_path, map|
|
|
84
|
+
map[abs_path.sub("#{abs_base}/", '')] = abs_path
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def parse_forms form
|
|
89
|
+
form.split(',').map { |f| f.strip.to_sym }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def resolve_paths path, exts
|
|
93
|
+
result = Sourcerer::Util::Pathifier.match(path)
|
|
94
|
+
result.type == :dir ? result.enum.select { |p| exts.any? { |e| p.end_with?(e) } } : result.enum.to_a
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def resolve_syntax syntax, form
|
|
98
|
+
return :yaml unless form
|
|
99
|
+
|
|
100
|
+
syntax = 'yaml' if syntax == 'yml'
|
|
101
|
+
puts
|
|
102
|
+
return syntax.to_sym if syntax
|
|
103
|
+
|
|
104
|
+
:json
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -146,8 +146,8 @@ module DocOpsLab
|
|
|
146
146
|
require 'erb'
|
|
147
147
|
|
|
148
148
|
unless agent_prompt
|
|
149
|
-
template_path =
|
|
150
|
-
agent_prompt = File.read(template_path) if File.exist?(template_path)
|
|
149
|
+
template_path = Library.resolve('templates/spellcheck.prompt.yml')
|
|
150
|
+
agent_prompt = File.read(template_path) if template_path && File.exist?(template_path)
|
|
151
151
|
end
|
|
152
152
|
|
|
153
153
|
# Create the YAML content with ERB templating for better formatting
|
|
@@ -6,36 +6,35 @@ require 'pathname'
|
|
|
6
6
|
|
|
7
7
|
module DocOpsLab
|
|
8
8
|
module Dev
|
|
9
|
+
# rubocop:disable Metrics/ModuleLength
|
|
9
10
|
module SyncOps
|
|
10
|
-
# rubocop
|
|
11
|
+
# rubocop:disable Metrics/ClassLength
|
|
11
12
|
class << self
|
|
12
13
|
def install_vale_styles context
|
|
13
|
-
return unless File.exist?(
|
|
14
|
+
return unless File.exist?(Paths::CONFIG_FILES[:vale]) && context.tool_available?('vale')
|
|
14
15
|
|
|
15
|
-
puts "📚 Syncing Vale styles using Packages key in #{
|
|
16
|
-
context.run_with_fallback('vale', "vale --config=#{
|
|
16
|
+
puts "📚 Syncing Vale styles using Packages key in #{Paths::CONFIG_FILES[:vale]} (local and remote packages)"
|
|
17
|
+
context.run_with_fallback('vale', "vale --config=#{Paths::CONFIG_FILES[:vale]} sync")
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def sync_vale_styles context, local: false
|
|
20
21
|
puts '📚 Syncing Vale styles...'
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
unless Library.available?
|
|
24
|
+
puts '❌ Library not available; run `labdev:sync:library` to fetch.'
|
|
25
|
+
return false
|
|
26
|
+
end
|
|
27
|
+
styles_source_root = Library.resolve('config-packs/vale')
|
|
28
|
+
unless styles_source_root
|
|
29
|
+
puts '❌ config-packs/vale not found in library; run `labdev:sync:library` to fetch.'
|
|
30
|
+
return false
|
|
31
|
+
end
|
|
29
32
|
styles_dest_root = '.config/.vendor/vale/styles'
|
|
30
33
|
FileUtils.mkdir_p(styles_dest_root)
|
|
31
34
|
|
|
32
35
|
# Get the list of local styles from tools.yml
|
|
33
36
|
begin
|
|
34
|
-
tools_yml_path =
|
|
35
|
-
'gems/docopslab-dev/specs/data/tools.yml'
|
|
36
|
-
else
|
|
37
|
-
File.join(GEM_ROOT, 'specs', 'data', 'tools.yml')
|
|
38
|
-
end
|
|
37
|
+
tools_yml_path = Dev.tools_def_path
|
|
39
38
|
|
|
40
39
|
style_paths_array = YAML.load_file(tools_yml_path)
|
|
41
40
|
.find { |t| t['slug'] == 'vale' }['packaging']['packages']
|
|
@@ -77,7 +76,7 @@ module DocOpsLab
|
|
|
77
76
|
# If not local-only, also run Vale sync for remote styles
|
|
78
77
|
unless local
|
|
79
78
|
puts '📦 Syncing remote Vale packages...'
|
|
80
|
-
vale_config =
|
|
79
|
+
vale_config = Paths::CONFIG_FILES[:vale]
|
|
81
80
|
context.generate_vale_config unless File.exist?(vale_config)
|
|
82
81
|
context.run_with_fallback('vale', "vale --config=#{vale_config} sync")
|
|
83
82
|
end
|
|
@@ -92,6 +91,12 @@ module DocOpsLab
|
|
|
92
91
|
docs_entries = manifest['docs']
|
|
93
92
|
return false unless docs_entries.is_a?(Array)
|
|
94
93
|
|
|
94
|
+
lib_root = Library.root
|
|
95
|
+
unless lib_root
|
|
96
|
+
puts '❌ Library not available; run `labdev:sync:library` to fetch.'
|
|
97
|
+
return false
|
|
98
|
+
end
|
|
99
|
+
|
|
95
100
|
puts '📚 Syncing documentation files...'
|
|
96
101
|
|
|
97
102
|
synced_count = 0
|
|
@@ -107,16 +112,14 @@ module DocOpsLab
|
|
|
107
112
|
next unless source_pattern
|
|
108
113
|
next if synced # Only collect exclusions
|
|
109
114
|
|
|
110
|
-
# Resolve source file path
|
|
115
|
+
# Resolve source file path relative to library root
|
|
111
116
|
if source_pattern.include?('*')
|
|
112
|
-
|
|
113
|
-
source_glob = File.join(GEM_ROOT, source_pattern)
|
|
117
|
+
source_glob = File.join(lib_root, source_pattern)
|
|
114
118
|
Dir.glob(source_glob).each do |source_file|
|
|
115
119
|
excluded_files.add(source_file) if File.file?(source_file)
|
|
116
120
|
end
|
|
117
121
|
else
|
|
118
|
-
|
|
119
|
-
source_file = File.join(GEM_ROOT, source_pattern)
|
|
122
|
+
source_file = File.join(lib_root, source_pattern)
|
|
120
123
|
excluded_files.add(source_file) if File.exist?(source_file)
|
|
121
124
|
end
|
|
122
125
|
end
|
|
@@ -134,8 +137,7 @@ module DocOpsLab
|
|
|
134
137
|
|
|
135
138
|
# Check if source is a glob pattern
|
|
136
139
|
if source_pattern.include?('*')
|
|
137
|
-
|
|
138
|
-
source_glob = File.join(GEM_ROOT, source_pattern)
|
|
140
|
+
source_glob = File.join(lib_root, source_pattern)
|
|
139
141
|
matching_files = Dir.glob(source_glob)
|
|
140
142
|
|
|
141
143
|
if matching_files.empty?
|
|
@@ -147,13 +149,18 @@ module DocOpsLab
|
|
|
147
149
|
next unless File.file?(source_file)
|
|
148
150
|
next if sources_checked.include?(source_file)
|
|
149
151
|
|
|
150
|
-
# Skip if explicitly excluded
|
|
151
152
|
if excluded_files.include?(source_file)
|
|
152
153
|
puts " ⏭️ Skipped #{File.basename(source_file)} (explicitly excluded)"
|
|
153
154
|
next
|
|
154
155
|
end
|
|
155
156
|
|
|
156
|
-
#
|
|
157
|
+
# Guard: docs/agent/AGENTS.md was relocated to templates/AGENTS.markdown.
|
|
158
|
+
if source_file.end_with?('docs/agent/AGENTS.md')
|
|
159
|
+
puts ' ⏭️ Skipped docs/agent/AGENTS.md \
|
|
160
|
+
(relocated to templates/AGENTS.markdown; remove from manifest)'
|
|
161
|
+
next
|
|
162
|
+
end
|
|
163
|
+
|
|
157
164
|
filename = File.basename(source_file)
|
|
158
165
|
target_file = File.join(target_path, filename)
|
|
159
166
|
|
|
@@ -163,11 +170,11 @@ module DocOpsLab
|
|
|
163
170
|
skipped_count += 1 if result == :skipped
|
|
164
171
|
end
|
|
165
172
|
else # Single file
|
|
166
|
-
source_file = File.join(
|
|
173
|
+
source_file = File.join(lib_root, source_pattern)
|
|
167
174
|
|
|
168
175
|
unless File.exist?(source_file)
|
|
169
176
|
puts " ❌ Source file not found: #{source_file}"
|
|
170
|
-
puts " Run 'bundle exec rake
|
|
177
|
+
puts " Run 'bundle exec rake labdev:sync:library` then 'labdev:sync:docs' to refresh"
|
|
171
178
|
next
|
|
172
179
|
end
|
|
173
180
|
|
|
@@ -179,6 +186,12 @@ module DocOpsLab
|
|
|
179
186
|
next
|
|
180
187
|
end
|
|
181
188
|
|
|
189
|
+
# Guard: docs/agent/AGENTS.md was relocated to templates/AGENTS.markdown.
|
|
190
|
+
if source_file.end_with?('docs/agent/AGENTS.md')
|
|
191
|
+
puts ' ⏭️ Skipped docs/agent/AGENTS.md (relocated to templates/AGENTS.markdown; remove from manifest)'
|
|
192
|
+
next
|
|
193
|
+
end
|
|
194
|
+
|
|
182
195
|
sources_checked << source_file
|
|
183
196
|
|
|
184
197
|
result = copy_doc_file(source_file, target_path, synced: synced, force: force)
|
|
@@ -198,6 +211,52 @@ module DocOpsLab
|
|
|
198
211
|
ScriptManager.sync_scripts
|
|
199
212
|
end
|
|
200
213
|
|
|
214
|
+
def sync_templates context, force: false
|
|
215
|
+
manifest = context.load_manifest
|
|
216
|
+
return false unless manifest
|
|
217
|
+
|
|
218
|
+
template_entries = manifest['templates']
|
|
219
|
+
return false unless template_entries.is_a?(Array)
|
|
220
|
+
|
|
221
|
+
lib_root = Library.root
|
|
222
|
+
unless lib_root
|
|
223
|
+
puts '❌ Library not available; run `labdev:sync:library` to fetch.'
|
|
224
|
+
return false
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
puts '📄 Syncing template files...'
|
|
228
|
+
|
|
229
|
+
synced_count = 0
|
|
230
|
+
skipped_count = 0
|
|
231
|
+
|
|
232
|
+
template_entries.each do |entry|
|
|
233
|
+
source_rel = entry['source']
|
|
234
|
+
target_path = entry['target']
|
|
235
|
+
synced = entry.fetch('synced', false)
|
|
236
|
+
|
|
237
|
+
next unless source_rel && target_path
|
|
238
|
+
|
|
239
|
+
source_file = File.join(lib_root, source_rel)
|
|
240
|
+
|
|
241
|
+
unless File.exist?(source_file)
|
|
242
|
+
puts " \u274c Template source not found: #{source_rel}"
|
|
243
|
+
puts ' Run `bundle exec rake labdev:sync:library` to fetch the latest library.'
|
|
244
|
+
next
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
result = copy_doc_file(source_file, target_path, synced: synced, force: force)
|
|
248
|
+
synced_count += 1 if result == :copied
|
|
249
|
+
skipped_count += 1 if result == :skipped
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
puts "\u2705 Synced #{synced_count} template file(s)" if synced_count.positive?
|
|
253
|
+
if skipped_count.positive?
|
|
254
|
+
puts "\u2139\ufe0f Skipped #{skipped_count} existing template(s) (use --force to overwrite)"
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
synced_count.positive? || skipped_count.positive?
|
|
258
|
+
end
|
|
259
|
+
|
|
201
260
|
def sync_config_files context, tool_filter: :all, offline: false
|
|
202
261
|
# Validate tool filter parameter
|
|
203
262
|
unless tool_filter == :all || tool_filter.is_a?(String) || tool_filter.is_a?(Symbol)
|
|
@@ -222,8 +281,9 @@ module DocOpsLab
|
|
|
222
281
|
return false
|
|
223
282
|
end
|
|
224
283
|
|
|
225
|
-
|
|
226
|
-
|
|
284
|
+
config_packs_root = Library.resolve('config-packs')
|
|
285
|
+
unless config_packs_root && Dir.exist?(config_packs_root)
|
|
286
|
+
puts '❌ config-packs not found in library; run `labdev:sync:library` to fetch.'
|
|
227
287
|
return false
|
|
228
288
|
end
|
|
229
289
|
|
|
@@ -270,7 +330,7 @@ module DocOpsLab
|
|
|
270
330
|
next
|
|
271
331
|
end
|
|
272
332
|
|
|
273
|
-
source_path = File.join(
|
|
333
|
+
source_path = File.join(config_packs_root, source_rel)
|
|
274
334
|
|
|
275
335
|
unless File.exist?(source_path)
|
|
276
336
|
puts " ❌ Source not found: #{source_rel}"
|
|
@@ -375,7 +435,7 @@ module DocOpsLab
|
|
|
375
435
|
obsolete_files = []
|
|
376
436
|
# Common vendor paths to check for obsolete files
|
|
377
437
|
vendor_patterns = [
|
|
378
|
-
File.join(
|
|
438
|
+
File.join(Paths.config_vendor_dir, '**', '*')
|
|
379
439
|
]
|
|
380
440
|
vendor_patterns.each do |pattern|
|
|
381
441
|
Dir.glob(pattern).each do |file_path|
|
|
@@ -462,7 +522,8 @@ module DocOpsLab
|
|
|
462
522
|
end
|
|
463
523
|
end
|
|
464
524
|
end
|
|
465
|
-
# rubocop
|
|
525
|
+
# rubocop:enable Metrics/ClassLength
|
|
466
526
|
end
|
|
527
|
+
# rubocop:enable Metrics/ModuleLength
|
|
467
528
|
end
|
|
468
529
|
end
|
data/lib/docopslab/dev/tasks.rb
CHANGED
|
@@ -54,11 +54,6 @@ module DocOpsLab
|
|
|
54
54
|
Dev.check_standard_rake_tasks
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
desc desc_for('check:updates')
|
|
58
|
-
task :updates do
|
|
59
|
-
Dev.check_hook_updates
|
|
60
|
-
end
|
|
61
|
-
|
|
62
57
|
desc desc_for('check:all')
|
|
63
58
|
task :all do
|
|
64
59
|
Rake::Task['labdev:check:env'].invoke
|
|
@@ -89,6 +84,11 @@ module DocOpsLab
|
|
|
89
84
|
puts '⚠️ Agent docs sync skipped or failed'
|
|
90
85
|
end
|
|
91
86
|
end
|
|
87
|
+
|
|
88
|
+
desc desc_for('init:templates')
|
|
89
|
+
task :templates do
|
|
90
|
+
CastOps.init_cast_targets(Dev)
|
|
91
|
+
end
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# ============================================================
|
|
@@ -135,9 +135,10 @@ module DocOpsLab
|
|
|
135
135
|
# end
|
|
136
136
|
|
|
137
137
|
desc desc_for('run:shellcheck')
|
|
138
|
-
task :shellcheck, [
|
|
138
|
+
task :shellcheck, %i[path opts] => [] do |_t, args|
|
|
139
|
+
path = args[:path]
|
|
139
140
|
opts = args[:opts] || ''
|
|
140
|
-
Dev.run_shellcheck(
|
|
141
|
+
Dev.run_shellcheck(path, opts)
|
|
141
142
|
end
|
|
142
143
|
|
|
143
144
|
desc desc_for('run:actionlint')
|
|
@@ -167,6 +168,13 @@ module DocOpsLab
|
|
|
167
168
|
Dev.sync_docs(force: true)
|
|
168
169
|
end
|
|
169
170
|
|
|
171
|
+
desc desc_for('sync:templates')
|
|
172
|
+
task :templates, %i[path dry] => [] do |_t, args|
|
|
173
|
+
target = args[:path]
|
|
174
|
+
dry = args[:dry].to_s.downcase == 'dry'
|
|
175
|
+
CastOps.sync_cast_targets(Dev, target_filter: target, dry_run: dry)
|
|
176
|
+
end
|
|
177
|
+
|
|
170
178
|
namespace :styles do
|
|
171
179
|
desc desc_for('sync:styles:local')
|
|
172
180
|
task :local do
|
|
@@ -210,11 +218,22 @@ module DocOpsLab
|
|
|
210
218
|
|
|
211
219
|
desc desc_for('sync:all')
|
|
212
220
|
task :all do
|
|
213
|
-
|
|
214
|
-
Dev.sync_scripts
|
|
215
|
-
Dev.sync_docs
|
|
221
|
+
Library.sync!
|
|
216
222
|
Dev.install_missing_hooks
|
|
217
223
|
Dev.sync_vale_styles
|
|
224
|
+
CastOps.sync_cast_targets(Dev)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
desc desc_for('sync:library')
|
|
228
|
+
task :library do
|
|
229
|
+
Library.sync!
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
namespace :library do
|
|
233
|
+
desc desc_for('sync:library:stage')
|
|
234
|
+
task :stage, [:path] => [] do |_t, args|
|
|
235
|
+
Library.stage!(source_path: args[:path])
|
|
236
|
+
end
|
|
218
237
|
end
|
|
219
238
|
end
|
|
220
239
|
|
|
@@ -262,17 +281,12 @@ module DocOpsLab
|
|
|
262
281
|
|
|
263
282
|
desc desc_for('lint:docs')
|
|
264
283
|
task :docs, %i[path rule opts] => [] do |_t, args|
|
|
265
|
-
path = args[:path]
|
|
284
|
+
path = args[:path] || '.'
|
|
266
285
|
rule = args[:rule]
|
|
267
286
|
opts = args[:opts]
|
|
268
287
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
target = path || nil
|
|
272
|
-
Dev.run_vale(target, opts || '', filter: filter)
|
|
273
|
-
else
|
|
274
|
-
Dev.run_linter_group('AsciiDoc', %w[vale])
|
|
275
|
-
end
|
|
288
|
+
filter = rule ? ".Name==#{rule}" : nil
|
|
289
|
+
Dev.run_vale(path, opts || '', filter: filter)
|
|
276
290
|
end
|
|
277
291
|
|
|
278
292
|
desc desc_for('lint:html')
|
|
@@ -398,6 +412,27 @@ module DocOpsLab
|
|
|
398
412
|
Help.show_task_help('heal')
|
|
399
413
|
end
|
|
400
414
|
|
|
415
|
+
# ============================================================
|
|
416
|
+
# SKIM tasks; Skim source files for machine-oriented outlines
|
|
417
|
+
# ============================================================
|
|
418
|
+
|
|
419
|
+
desc desc_for('skim')
|
|
420
|
+
task :skim, %i[path form syntax] => [] do |_t, args|
|
|
421
|
+
Skim.run(args[:path], form: args[:form], syntax: args[:syntax])
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
namespace :skim do
|
|
425
|
+
desc desc_for('skim:adoc')
|
|
426
|
+
task :adoc, %i[path form syntax] => [] do |_t, args|
|
|
427
|
+
Skim.run_adoc(args[:path], form: args[:form], syntax: args[:syntax])
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
desc desc_for('skim:md')
|
|
431
|
+
task :md, %i[path form syntax] => [] do |_t, args|
|
|
432
|
+
Skim.run_md(args[:path], form: args[:form], syntax: args[:syntax])
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
401
436
|
# ============================================================
|
|
402
437
|
# SHOW and HELP tasks; Display information
|
|
403
438
|
# ============================================================
|
|
@@ -427,6 +462,11 @@ module DocOpsLab
|
|
|
427
462
|
|
|
428
463
|
Dev.show_lint_rule(tool, rule)
|
|
429
464
|
end
|
|
465
|
+
|
|
466
|
+
desc desc_for('show:library')
|
|
467
|
+
task :library do
|
|
468
|
+
Library.print_status
|
|
469
|
+
end
|
|
430
470
|
end
|
|
431
471
|
|
|
432
472
|
desc desc_for('help')
|