Purpose

The docopslab-dev gem provides centralized configuration management, linting, and development workflows across DocOps Lab repositories.

This gem mainly provides Rakefile extensions and common assets like scripts, configuration files, styles packages, and git hooks.

Features

Focused development tooling

Centralized code quality, analysis, and linting tools (RuboCop, Vale, ShellCheck, etc.)

Unified Rake tasks

Consistent labdev:* tasks across all repos

Scripts management

Common scripts synchronized across projects

Config pack synchronization

Centralized configuration management for all development tools

Git hooks management

Automated pre-commit linting and validation with interactive updates

Docker image

Completely containerized docopslab-dev environment without local installation

Setup

If this is your first time using docopslab-dev on a given workstation, you will need to ensure the prerequisites are met.

If you have the prerequisites and are just getting started with a given DocOps Lab project, you should be ready after Initialize or Sync.

If you are initializing docopslab-dev in an new project, you will also need to initialize the environment.

Prerequisites

There are three ways to prepare the necessary dependencies and runtimes.

If you are already a Ruby user, Option 1 is likely for you. Otherwise, Option 2 is strongly recommended, at least for getting started quickly.

Option 1: Native Installations

Ruby & Bundler
  • Ruby 3.2+ with Bundler installed natively

  • gem 'docopslab-dev' in `Gemfile

  • All Ruby gems managed via bundle install

Vale
  • brew install vale (macOS)

  • apt install vale (Ubuntu/Debian)

  • dnf install vale (Fedora)

  • If not installed, vale operations will fallback to Docker execution

Asciidoctor (to support Vale)
  • installed globally

    • gem install asciidoctor or

    • npm i -g asciidoctor or

    • natively installed through your system’s package manager

  • Test with asciidoctor --version

ShellCheck
  • brew install shellcheck (macOS)

  • apt install shellcheck (Ubuntu/Debian)

  • dnf install shellcheck (Fedora)

  • If not installed, shellcheck operations will fallback to Docker execution

actionlint
  • brew install actionlint (macOS)`

  • go install github.com/rhysd/actionlint/cmd/actionlint@latest (Go 1.16 or later)

  • Otherwise see install guide.

  • If not installed, actionlint operations will fallback to Docker execution

gh (preferred) or git
  • brew install gh (macOS)

  • See install guide for Linux (APT, DNF, etc.)

  • Used for labdev:sync:library; falls back to git if not installed

Option 2: Full Docker Environment

The docopslab/dev image provides a complete development environment with Ruby, Vale, and all linting tools pre-installed.

Add an alias to your shell profile (~/.bashrc, ~/.zshrc, etc.) to make Docker usage easier:

alias lab-dev='docker run -it --rm -v "$(pwd):/workspace" docopslab/dev'

For Zshell users, the noglob command prefix is recommended to prevent formatting issues when passing arguments to tasks.

alias lab-dev='noglob docker run -it --rm -v "$(pwd):/workspace" docopslab/dev'

Be sure to run source ~/.bashrc or source ~/.zshrc or equivalent to instantiate the alias.

Now lab-dev replaces the full Docker command and causes insertion of bundle exec for rake or labdev: commands.

Option 3: Ruby with Docker fallback

  • Ruby & Bundler + Gemfile as in Option 1

  • Vale and other non-Ruby services run via Docker if not installed locally as in Option 2

  • All labdev: rake tasks that use non-Ruby dependencies will attempt native execution first, then fall back to Docker if the tool is not found or is found to be the wrong version.

Initialize or Sync

Once dependencies are installed, the development environment may need to be initialized and must be synced, between your local instance and source assets.

Assuming you are not initializing a new project, you can skip to Environment Synchronization.

Project Initialization

If you are introducing docopslab-dev to an existing project, you first need to integrate and initialize it.

  1. Add docopslab-dev to the project’s Gemfile.

    group :development do
      gem 'docopslab-dev'
    end
  2. Install the gem.

    bundle install
  3. Add require 'docopslab/dev' to the top of the project’s Rakefile.

    Note
    A project lacking any configuration files can now be initialized.
  4. Use bundle exec rake labdev:check to ensure the project environment is aligned.

  5. Initialize the development environment

    bundle exec rake labdev:init:all

The init task creates .config/docopslab-dev.yml and default project configs for all tools. This file should be Git tracked for the project.

Initialization also performs environment synchronization.

Environment Synchronization

This process is part of the init operation, but on its own it ensures local configs and assets are up to date with their source templates.

Install the dependencies (if not done already)
bundle install
Sync configuration files
bundle exec rake labdev:sync:all

Manifest File

Every project using docopslab-dev is configured through a single manifest file at .config/docopslab-dev.yml (created by labdev:init:all or manually).

The manifest has four top-level keys, each documented in detail in the relevant section:

tools:

Managed Tools: active linters and their config file mappings.

docs:

File Syncing > Cross-project Documentation: agent docs and guides to sync.

templates:

Template Sync Casting: Liquid-rendered source-to-target entries.

library:

Remote Asset Library: library source and cache settings.

Using the Tool (Rake Tasks)

This gem mainly supplies rake tasks for performing common development operations across and between projects.

Standard Usage

With a proper native Ruby environment, use the bundle exec prefix to ensure consistent dependency versioning.

Sync all configs and assets
bundle exec rake labdev:sync:all
Run all linters
bundle exec rake labdev:lint:all
Auto-fix safe issues
bundle exec rake labdev:heal:all

Docker Usage

The container runs with a base command of /bin/bash in interactive mode. Any command you pass it will assume you are starting at a normal prompt, with the exception of rake, which will always convert to bundle exec rake.

Other Ruby commands will either need an explicit lab-dev bundle exec or may run without Bundler, like asciidoctor (globally installed for Vale availability) and bundle itself. Non-Ruby commands like vale and shellcheck are immediately available.

First time in a DocOps Lab project
lab-dev :sync:all
Regular development workflow
lab-dev :sync:all
lab-dev :lint:all
lab-dev :heal
Irregular commands
lab-dev vale --config .config/vale.ini README.adoc
lab-dev bundle exec rubocop --config .config/rubocop.yml --only Style/StringLiterals
lab-dev asciidoctor -o tmp/docs.html README.adoc
Interactive shell for debugging
lab-dev
Note

The Docker container persists gems on the host machine in the local .bundle/ path for performance. All tools use the host project’s Gemfile for version consistency.

Tip

Make sure container-managed paths are not tracked in Git. Add .config/.vendor/, scripts/.vendor, and .bundle/ to .gitignore.

See [more-example-commands] for additional common commands.

Handy Tasks

Lint only for AsciiDoc syntax issues
bundle exec rake labdev:lint:adoc
Lint only for prose/text issues
bundle exec rake labdev:lint:text
Lint for both text and markup issues
bundle exec rake labdev:lint:docs
Get a Spelling report
bundle exec rake labdev:lint:spellcheck
Troubleshoot a Jekyll-AsciiDoc build
 # example docs gen
 bundle exec jekyll build --config .config/jekyll.yml --verbose > /tmp/logs/jekyll-build.log 2>&1
 # parse the logs for errors
 bundle exec rake labdev:lint:logs[jekyll,/tmp/logs/jekyll-build.log]
Generate a semantic index/outline of documentation source files
bundle exec rake labdev:skim:adoc[.,tree,json] > .agent/docs/docs-skim.json
Generate an index/outline of Agent-oriented Markdown files (with overlays)
bundle exec rake labdev:skim:md[.agent/docs/:_docs/agent/,tree,json] > .agent/docs/agent-docs-skim.json

Managed Tools

The docopslab-dev gem itself is orchestrated using a manifest file. This manifest declares which tools are active and their integration settings.

Individual configs are maintained for all supported tools in each project codebase. For each project implementation (application) of this coordinating gem, local configs inherit from centrally maintained “canonical” configs that ship with the gem. See File Syncing for details on how the synchronization process works.

Tools Manifest Configuration

Initialization automatically creates .config/docopslab-dev.yml, which you can edit, or you can create it manually.

See specs/data/default-manifest.yml for the default manifest structure.

Tools Properties Reference

The following parameters are available for each record in the tools: block of the manifest.

tool

(Slug, required) Name of the tool, ex:, rubocop, vale, htmlproofer, actionlint, shellcheck.

enabled

(Boolean) Whether to enable this tool’s tasks and git hooks.

manifest

(Array of Maps, required) Listing of files to init or sync for the tool. Each entry supports the following properties:

source

(Path, required) Path within the asset library where the base config is located, e.g., config-packs/rubocop/base.yml.

target

(Path, required) Path in the project where the file should be synced, e.g., .config/.vendor/docopslab/rubocop.yml.

paths

(Map) Repo-specific paths to include or exclude in linting operations for this tool.

lint

(Array) List of paths or glob patterns to lint with this tool.

skip

(Array) List of paths or glob patterns to exclude from linting with this tool.

exts

(Array) List of file extensions to include in linting with this tool.

git_tracked_only

(Boolean) Whether to limit linting to only Git-tracked files.

RuboCop

Ruby code style and quality checking.

Base config

.config/.vendor/docopslab/rubocop.yml

Project config

.config/rubocop.yml (inherits via inherit_from)

Sync command

bundle exec rake labdev:sync:configs

The base configuration provides DocOps Lab Ruby style standards. Your project config can override any rule while maintaining consistency with the broader ecosystem.

Vale

Linting for documentation quality and consistency, both AsciiDoc markup syntax and prose quality/correctness.

This tool provides a custom styles package and a modified configuration system, enabling multi-file merging.

Base config

.config/.vendor/docopslab/vale.ini (from source)

Project config

.config/vale.local.ini (inherits via BasedOnStyles)

Ephemeral config

.config/vale.ini (merged from base and target)

Sync command

bundle exec rake labdev:sync:vale

Consumer Mode (Other Projects)

For all other projects, the gem works in a standard package consumption mode:

  • The project’s vale.ini should list all desired packages, including a URL to the stable, published DocOpsLabStyles.zip.

  • The labdev:sync:styles task simply runs vale sync in the proper context, downloading all listed packages into a local .vale/styles directory.

Tip
The labdev:sync:vale task updates both the base config and the style packages.

A project’s .config/vale.local.ini should look something like the one for this repository (DocOps/lab).

A snippet from DocOps/lab’s .config/vale.local.ini
link:../../.config/vale.local.ini[role=include]

This dual-mode system provides a robust workflow for both developing and consuming the centralized Vale styles.

Note
For full Vale configuration settings (“keys”) reference, see the official Vale documentation.

HTMLProofer

HTML validation for Jekyll sites and documentation builds.

Base config

.config/.vendor/docopslab/htmlproofer.yml

Project config

.config/htmlproofer.yml

Sync command

bundle exec rake labdev:sync:configs

Enable in manifest

Add htmlproofer tool with enabled: true

HTMLProofer validates links, images, and HTML structure in built sites. Only enabled for projects that generate HTML output (Jekyll sites, etc.).

Default base config is in gems/docopslab-dev/assets/config-packs/htmlproofer/base.yml.

Note
For full HTMLProofer configuration options, see the official docs.

File Syncing

This gem enables central/upstream authorship and maintenance of technical documentation and other flat-file content, with flexible syncing to downstream projects.

Sync Categories

Category Manifest key Primary task(s)

Documentation (whole-file)

docs:

labdev:sync:docs

Tool configs

tools:

labdev:sync:configs

Scripts

none

labdev:sync:scripts

Git hooks

none

labdev:sync:hooks

Templates (Sync/Cast)

templates:

labdev:sync:templates

Run labdev:sync:all to execute all sync operations in one command.

Types of File-sync Operations

The docopslab-dev tool supports two main types of syncing operations, each with different use cases and behaviors.

whole-file syncing

Maintain a local copy of centrally managed files like developer documentation, tool configs, and automation scripts. This is the main syncing pattern.

template sync casting

Maintain canonical sections of code or text in files that need to be partially customized but also regularly updated from a central source.

stub initialization

This is actually just an instance of casting that is not kept in sync after being written to the codebase during an init operation.

File Syncing Semantics

Files are kept in sync under the following categorical semantics:

documentation (docs)

Whole directories of documentation files that are authored in the DocOps/lab repo and synced to projects using rake labdev:sync:docs.

tool configuration files (configs)

Files tied dependency tools like Vale and RuboCop. Synced using rake labdev:sync:configs.

scripts

All files in scripts/.vendor/ path (rake labdev:sync:scripts).

Git hooks (hooks)

All Git hooks from the assets library (rake labdev:sync:hooks).

linter styles/rules (styles)

Specific rulesets mapped to linters, including third-party origins.

Vale linter (vale)

Includes Vale styles and config, together (rake labdev:sync:vale).

Liquid/casting templates

Files that are rendered using Liquid syntax and/or canonical block resolution. Uses rake labdev:sync:templates or rake labdev:sync:templates[.gitignore] for a specific file.

The command rake labdev:sync:all performs all syncing operations in one go.

Whole-file Syncing Operations

When we talk about “whole file” vs “templated” file syncing, we refer strictly to the relationship with upstream/centralized canonical sources. Even whole-file syncing does not mean the downstream version of such files are what affects the system.

Configs can generally be merged with local settings, whereas documents and scripts tend to be replaced by local alternates.

Cross-project Documentation

The gem manages LLM/agent-oriented documentation that can be synced to downstream projects for local availability. Some files and paths are highlighted here.

Specific instruction files for AI agents working with common tools and patterns. For instance, local paths:

  • .agent/skills/git.md

  • .agent/skills/fix-spelling-issues.md

  • .agent/missions/conduct-release.md

Such files are sourced as AsciiDoc in DocOps/lab/_docs/agent/, largely reusing content from people-facing docs sourced in _docs/reference/ and _docs/tasks/.

In most contexts, agents are instructed to check for a parallel file in the local project’s docs/ directory that would supersede the locally synced copy.

Tool Configs and Scripts

Tool configs, linter styles, scripts, and Git hooks are all synced as part of labdev:sync:all. Most have no per-project manifest configuration; they are sourced from the centrally managed library and written to conventional paths.

Configs and linter styles

Synced by labdev:sync:configs, labdev:sync:vale, labdev:sync:styles, and labdev:sync:all, depending on intent.

These types of files are generally merged with existing local versions, rather than replaced, to preserve any project-specific customizations while still applying updates from the central source.

Scripts

Synced to scripts/.vendor/docopslab/ using labdev:sync:scripts. Local overrides placed at scripts/ take precedence over upstream versions of the same filename, though of course they can execute the upstream-sourced scripts.

Git hooks

Synced to .git/hooks/ with labdev:sync:hooks. Git hooks do not have a merge or override system; they are either present or not.

Template Sync Casting

While most docopslab-dev file-sync operations are standard (whole-file replacement), the concept of sync casting deserves more attention.

Template sync casting keeps project files (targets) up to date with upstream canonical source templates (primes) using the AsciiSourcerer::Sync::Cast model and engine.

Casting can swap whole blocks of code, and it can render Liquid syntax, on a one-time or ongoing basis.

Liquid can be used anywhere in the source/prime template. It will be processed during init operations for full rendering of the initial file.

During sync operations, casting will render Liquid syntax in canonical block content only.

Liquid Context

While the canonical blocks are sourced right in the source template file, data used to render Liquid-tagged content must come from an external source.

runtime variables

At runtime, project attributes are derived from the README.adoc file and made available to all templates as {{ data.project.attributes.<attr_key_name> }}.

manifest assignment

Data objects (variables) can be defined in the manifest, alongside a given instance of the mapping. These are available as {{ data.variables.<object> }} in the template, where <object> is the name of a String, Boolean, Number, Array, or Map variable type.

local/inherited assignment

Standard Liquid variables established with {% assign %} or `{% capture %} tags in templates or arguments passed to Jekyll-style {% include %} tags.

Operations

Two operations are available:

labdev:init:templates

Bootstrap new target files from their source templates. During init, the entire source template is rendered through Liquid before writing, so every {{ data.project.attributes.name }} or {{ data.variables.my_key }} placeholder anywhere in the document is resolved. Targets that already exist are skipped.

labdev:sync:templates

Update canonical blocks in existing target files from the source template. During sync, only the content inside canonical blocks is rendered through Liquid. Content outside blocks is sourced from the target, not the source template, so template syntax outside blocks is never touched.

Bootstrap all configured targets
bundle exec rake labdev:init:templates
Sync all configured targets
bundle exec rake labdev:sync:templates
Sync a single target (by its target path)
bundle exec rake 'labdev:sync:templates[AGENTS.md]'
Preview a single target without writing
bundle exec rake 'labdev:sync:templates[AGENTS.md,dry]'

The bulk sync is also included in labdev:sync:all.

Manifest Configuration

This reference covers the properties relevant to file syncing and sync casting in the manifest file at .config/docopslab-dev.yml.

The docs: block in the manifest is itself a manifest array. Each entry supports the following properties:

source

(Path, required) Source path relative to lib/docopslab/ in the gem. Supports glob patterns (e.g., docs/agent/*.md) or specific files.

target

(Path, required) Target path relative to the project root. Can be a directory (e.g., _docs/) or specific file path (e.g., AGENTS.md).

synced

(Boolean) Whether to update existing files on sync.

  • true - Always overwrite on sync (keeps docs current with gem updates)

  • false - Create once, preserve user customizations

The templates: block in the manifest is a Map that nests its own manifest: listing as well as global data ingestion directives in data:.

manifest

(Array) Listing of prime templates and their downstream target files for Sync/Cast operations, optionally passing additional data.

source

(String) The path to the source template file, library relative (resolved via labdev:sync:library).

target

(String) The path in the project where the rendered template should be synced, relative to the project root.

data

(Map) Optional additional data to pass to the template rendering process.

data.variables

(Map) Key-value pairs of variables bearing any value type to pass to the template rendering process, accessible as {{ data.variables.<key> }} in templates.

Template Manifest Configuration

Entries are declared under the templates.manifest: key in .config/docopslab-dev.yml. The key takes a Hash with two children: a global data: node and a manifest: list.

templates:
  data:                          # Global data available to all entries
    variables:
      project_name: "My Project"
  manifest:
    - source: templates/AGENTS.markdown   # Library-relative source template path
      target: AGENTS.md                   # Project-local target path
    - source: templates/custom.adoc
      target: docs/custom.adoc
      data:                               # Per-entry overrides, merged on top of global
        variables:
          extra_key: "value"

For a full property reference, see the comments in specs/data/default-manifest.yml in the gem source.

Liquid Template Context

All Liquid variables are scoped under the top-level data key:

data.project.attributes.<key>

Document attributes loaded from the project’s README.adoc header. Asciidoctor built-in attributes are filtered out; only user-defined string attributes are available.

data.variables.<key>

Merged from global data.variables and the per-entry data.variables override. Per-entry values take precedence.

{{ data.project.attributes.this_proj_name }}
{{ data.variables.description }}
Tip

During init, Liquid is rendered across the entire source template, so all {{ data.* }} references anywhere in the file are resolved. During sync, only the content inside canonical blocks is rendered; template syntax outside blocks is intentional scaffolding and will never be evaluated.

Block Syntax

Canonical blocks use the same AsciiDoc tag syntax as the rest of the DocOps Lab toolchain, wrapped in file-appropriate comments.

AsciiDoc / Markdown (HTML comment wrapper)
<!-- tag::example-text[] -->
This content is managed in the source template.
<!-- end::example-text[] -->
AsciiDoc (native comment)
// tag::example-source[]
This content is managed in the prime template.
// end::example-source[]

The canonical_prefix: setting controls which tagged blocks are treated as canonical. By default this is universal-. A target may contain alternate-prefixed blocks (e.g. local-agency) as a cue to the engine that a canonical block has been intentionally replaced; no warning is emitted for those.

Typical Workflow

The expected workflow for a new project:

  1. Register the entry in .config/docopslab-dev.yml under templates.manifest.

  2. Run labdev:init:templates to bootstrap the target file.

  3. Customize the project-specific sections (outside canonical blocks).

  4. As the source template evolves upstream, run labdev:sync:templates to pull in updated canonical blocks without disturbing local content.

Remote Asset Library

The docopslab-dev fetches a centrally managed asset library from the labdev-library branch of DocOps/lab and caches it host-wide at ~/.cache/docopslab/dev/library/. This enables updates per-project updates to config packs, templates, docs, hooks, and scripts without needing to update the gem package or re-download the remote library.

Cache Layout

The library cache lives at ~/.cache/docopslab/dev/library/ (or under $XDG_CACHE_HOME/docopslab/dev/library/ if that variable is set):

~/.cache/docopslab/dev/library/
  current/          # Active snapshot used by sync and resolve operations
    catalog.json    # Catalog with version, ref, and checksums
    config-packs/
    docs/
    hooks/
    scripts/
    templates/
  previous/         # Prior snapshot retained for fast rollback

Updates are never automatic. Run labdev:sync:library explicitly to pull a new snapshot. The prior snapshot is preserved as previous/ so a broken update can be rolled back immediately.

On first use, sync operations auto-fetch the library if no cache exists.

Library Configuration

Add a library: block to .config/docopslab-dev.yml to configure the source. All fields are optional; defaults target the labdev-library branch of DocOps/lab.

library:
  enabled: true
  source:
    type: git-branch
    repo: DocOps/lab
    ref: labdev-library
    path: library
  sync:
    mode: latest-only
    cache_root: ~/.cache/docopslab/dev/library
  # Optional: local fallback path when XDG cache is absent.
  # Populated by `bundle exec rake gemdo:push:library:stage` in DocOps/lab.
  local_path: .library

Library Tasks (Consumer Projects)

Fetch and cache the latest remote library
bundle exec rake labdev:sync:library
Show current library cache status and version
bundle exec rake labdev:show:library
Note
The fetch tasks require either the gh CLI or git to be available on your PATH. The gh CLI is preferred and will be used when present.

Task Reference

bundle exec rake --tasks | grep labdev:
Tip

To hide the labdev: tasks from the standard rake --tasks output for an integrated project, use:

bundle exec rake --tasks | grep -v labdev:

Typical Workflow

This tool is for working on DocOps Lab projects or possibly unrelated projects that wish to follow our methodology. A typical workflow might look as follows.

Normal development
git add .
git commit -m "Add new feature"

+ This should yield warnings and errors if active linters find issues.

  1. Auto-fix what you can.

    bundle exec rake labdev:heal:all
  2. Review the changes.

    git diff
  3. Commit the fixes.

    git add -A
    git commit -m "Auto-fix linting issues"
  4. Handle any remaining manual fixes.

    bundle exec rake labdev:lint:all
  5. Fix remaining issues manually.

    git add -A
    git commit -m "Fix remaining linting issues"
  6. Try pushing.

    git push

    If all blocking issues are cleared, the push should succeed. Otherwise, more cleanup is needed.

Tip

Bypass the pre-push gates (usually to test or demo the failure at origin):

git push --no-verify

Override Commands

Most executions of the packaged tools are handled through Rake tasks, but you can always run them directly, especially to pass arguments not built into the tasks.

RuboCop
bundle exec rubocop --config .config/rubocop.yml [options]
bundle exec rubocop --config .config/rubocop.yml --auto-correct-all
bundle exec rubocop --config .config/rubocop.yml --only Style/StringLiterals
Vale
vale --config=.config/vale.ini [options] [files]
vale --config=.config/vale.ini README.adoc
vale --config=.config/vale.ini --minAlertLevel=error .
HTMLProofer
 bundle exec htmlproofer --ignore-urls "/www.github.com/,/foo.com/" ./_site
// end::standard-usage[]
// end::usage[]
// end::workflow[]

Customization

Override settings by editing the project configs:

  • .config/docopslab-dev.yml

  • .config/rubocop.yml

  • .config/vale.ini

  • .config/htmlproofer.yml

  • .config/actionlint.yml

  • .config/shellcheckrc

Your configurations will inherit from the base configurations and source libraries as sourced in the Git-ignored .config/.vendor/docopslab/ path.

Local Overrides

Projects using docopslab-dev will have a configuration structure like the following:

.config/
├── docopslab-dev.yml             # Project manifest (tracked)
├── actionlint.yml                # Project config (tracked; inherits from base)
├── htmlproofer.local.yml         # Project config (tracked; inherits from base)
├── htmlproofer.yml               # Generated config (untracked)
├── rubocop.yml                   # Project config (tracked; inherits from base)
├── shellcheckrc                 # ShellCheck config (tracked)
├── vale.ini                      # Generated active config (untracked)
├── vale.local.ini                # Project config (tracked; inherits from base)
├── .vendor/                      # Base configs (untracked; synced)
│   └── docopslab/
│       ├── htmlproofer.yml       # Centrally managed base
│       ├── rubocop.yml           # Centrally managed base
│       └── vale.ini              # Centrally managed base
scripts/                          # Project override scripts
    └── .vendor/                  # Centrally managed scripts
.github/workflows/                # CI/CD workflows (tracked)
env.docopslab                     # Environment variables (git tracked)
env.private                       # Environment variables (git ignored)

Development

This gem is developed within the DocOps Lab monorepo at /gems/docopslab-dev/.

This section pertains to working on the docopslab-dev tool, rather than working with it.

Strategy and Aims

In addition to centralized configuration, script, docs, and hooks management, the gem aims to cover:

  • Central documentation build tooling (probably to spin off as docopslab-docs gem)

  • RSpec test framework management and templates

  • Security analysis (Brakeman, Bundler Audit)

  • Dependency management (Dependabot)

  • More CI/CD workflow templates

  • Generative AI agent templates and MCP infrastructure

  • Linting of SGYML YAML files

  • Linting of AsciiDoc/Markdown content stored in YAML files

Contributions in these directions are welcome.

Making Changes

There are two types of changes

  1. Edit files in lib/ or assets/.

  2. Test with lab repo as consumer.

For changes to docs or assets:

  1. Run linters on any scripts or content added.

  2. Publish independently using the base repo’s Rake tasks (rake gemdo:push:library).

For changes to functionality in lib/docopslab/dev/:

  1. Add or update RSpec tests in spec/ and ensure they pass.

  2. Update version in lib/docopslab/dev/version.rb.

  3. Run linters on any Ruby and docs changes.

  4. Update this README.adoc with new features or changed functionality.

Asset Resolution Policy

To ensure that AI agents and tools have reliable access to resources while allowing for project-specific overrides, docopslab-dev follows a local-first resolution policy for most assets.

Prompt Templates

Downstream scripts (like the Jekyll-AsciiDoc log parser) resolve prompt templates using the following order:

  1. Local Project Override: .config/prompts/<filename> (Git-tracked or user-defined).

  2. Upstream Library Fallback: templates/<filename> inside the host-wide library cache (e.g., ~/.cache/docopslab/dev/library/current/templates/).

This pattern ensures that a project can always "pin" or customize its agent interactions locally without breaking the default provided by the toolchain.

Configuration and Scripts

Scripts

The labdev:run:scripts task searches scripts/ (local) before scripts/.vendor/docopslab/ (synced).

Configs

Linter configurations are generally merged, with the local .config/ version taking precedence over the bundled vendor versions.

Submodule API Pattern

Each feature area lives in its own submodule under DocOpsLab::Dev (e.g., Library, SyncOps, ConfigManager). New public methods must be exposed on the submodule directly:

DocOpsLab::Dev::Library.fetch!
DocOpsLab::Dev::Library.resolve('templates/README.asciidoc')

The top-level DocOpsLab::Dev class surface (Dev.library_fetch!, etc.) is a backward-compatibility layer only and should not receive new methods. Callers consuming library features from Rake tasks or other modules should reference the submodule path, not the Dev facade.

Running Vale in Development Mode

When running within the DocOps/lab monorepo, the labdev:sync:styles task operates in a special development mode:

  • It copies the local, custom styles (e.g., DocOpsLab-Authoring, DocOpsLab-AsciiDoc) directly from the gem’s source (gems/docopslab-dev/assets/config-packs/vale/) into your project’s .config/.vendor/vale/styles/ directory.

  • It also runs vale sync to download any remote packages like RedHat or proselint into that same directory.

  • This allows you to edit the custom styles in the gem and see your changes immediately when you run the linter.

The .config/vale.ini for this mode should use the project’s local defaults for .config/vale.local.ini.

Building docopslab-dev Artifacts

To build the gem package:

bundle exec rake gemdo:build_gem

To build the docopslab/dev Docker image:

bundle exec rake gemdo:build_docker

Publish & Deploy Artifacts

For general DocOps Lab release procedures, see Release Process (General).

The docopslab-dev gem and docopslab/dev Docker image follow that process with these specific considerations:

Note
To publish the assets library, see the main DocOps/lab README.

Publishing Requirements

  • RubyGems.org account with MFA enabled

  • Docker Hub account with push access to docopslab organization

  • Clean local build environment (no uncommitted changes)

  • All tests passing (bundle exec rspec)

  • Version bumped in lib/docopslab/dev/version.rb

  • Agent documentation generated (bundle exec rake gemdo:generate_agent_docs)

Publishing the Gem

Build and publish to RubyGems.org:

cd gems/docopslab-dev
bundle exec rake build
gem push pkg/docopslab-dev-<version>.gem

RubyGems.org will prompt for MFA code during push. You must have valid authentication for an account with permissions to publish this gem.

Publishing the Docker Image

Build and push to Docker Hub:

cd gems/docopslab-dev
docker build -t docopslab/dev:<version> -t docopslab/dev:latest .
docker push docopslab/dev:<version>
docker push docopslab/dev:latest

Both version-specific and :latest tags should be published.

Testing Published Artifacts

Verify the gem installation from RubyGems.org:

gem install docopslab-dev
lab-dev --version

Verify the Docker image from Docker Hub:

docker pull docopslab/dev:latest
docker run --rm docopslab/dev:latest lab-dev --version

Test in a fresh project directory to ensure all dependencies install correctly:

mkdir /tmp/test-lab-dev
cd /tmp/test-lab-dev
echo 'source "https://rubygems.org"' > Gemfile
echo 'gem "subtxt"' >> Gemfile
docker run --rm -v "$PWD:/workspace" -w /workspace docopslab/dev:latest bundle exec subtxt --help

Functional code and data files released under MIT License.

Documentation released under Creative Commons Attribution 4.0 International (CC BY 4.0).

Bill of Materials

No externally sourced content or code is contained in this project. All third-party dependencies are permissively licensed and are downloaded independently, never provided by DocOps Lab.