Skip to content
vWorld
Menu
  • Main Page
  • About
  • Study Guide
    • VCAP-CMA Deploy 2018
Menu

Automating vRO Workflow Documentation with GitHub Actions

Posted on June 26, 2025June 26, 2025 by admin

Anyone who works with vRealize Orchestrator (vRO) daily knows the pain of documentation. Manually creating and updating descriptions for workflows, their inputs, outputs, variables, and logic is time-consuming, error-prone, and often neglected. The result is hundreds of workflows that no one fully understands, making them difficult to maintain, reuse, and develop.

But what if we could fully automate this process? What if the documentation generated itself with every code change, ensuring it’s always up-to-date and reflects the actual state of the workflow?

In this article, I present a complete solution based on GitHub Actions and a set of Node.js scripts that brings the “Documentation as Code” philosophy to the world of vRO. We will analyze how to automatically validate, lint, and generate detailed Markdown documentation for every workflow in your repository.

The Philosophy: Why This Works

Before diving into the code, let’s understand the fundamental shift in approach:

  1. Single Source of Truth: The workflow code (the .xml files) stored in Git becomes the single and ultimate source of truth. The documentation is a direct reflection of it, not a separate entity.
  2. Automation and Repeatability: The process is 100% automated. This eliminates the human factor, errors, and “forgetting” to update documents.
  3. Early Error Detection (Shift-Left): Thanks to automatic validation and linting, issues with naming conventions, missing descriptions, or script errors are caught at the Pull Request stage, not in production.
  4. Integration with the Software Development Lifecycle (SDLC): Documentation becomes an integral part of the development process, not an additional, disliked chore.

Tool Analysis: The Heart of the System

Our solution relies on several specialized JavaScript (Node.js) scripts that work together to achieve the goal.

1. parse-vro.js – The XML-to-Object Translator

The ability to read and understand the .xml files exported from vRO is the foundation of everything. This script acts as a translator.

  • Purpose: It reads a workflow XML file, parses it using the xml2js library, and converts it into an easy-to-use JavaScript object.
  • Key Function: loadXml() reads the file, and extractScripts() pulls out all embedded Scriptable Tasks, preparing them for further analysis.
// scripts/parse-vro.js
import { promises as fs } from 'node:fs';
import { parseStringPromise } from 'xml2js';

export async function loadXml(file) {
  const xml = await fs.readFile(file, 'utf8');
  return parseStringPromise(xml, { explicitArray: false, mergeAttrs: true, explicitCharkey: true });
}

2. validate-workflow.js – The Quality Gatekeeper

This script is our automated code reviewer. It ensures that every workflow meets predefined quality standards before it even reaches the main branch.

  • Purpose: To verify naming conventions and the quality of descriptions.
  • What It Checks:
    • Naming: Variables and parameters must be in lowerCamelCase, while constants (read-only attributes) must be in UPPER_CASE.
    • Descriptions: Every parameter, variable, and workflow element (except start/end) must have a description that is not empty, too short, or the default text from vRO.

// Snippet from validate-workflow.js
function validateName(name, constant) {
  return constant ? UPPER_CASE_RE.test(name) : CAMEL_CASE_RE.test(name);
}

// ...

if (!validateName(name, constant)) {
  console.error(`${fileRel}: variable "${name}" violates naming convention...`);
  violations++;
}

3. lint-workflow.js & eslint.config.js – The Code Stylist

vRO workflows often contain embedded JavaScript. This script, combined with the ESLint configuration, ensures that this code is clean, consistent, and follows best practices.

  • Purpose: Static analysis of the JavaScript code inside the workflow.
  • How It Works:
    1. It uses parse-vro.js to extract all scripts.
    2. It runs the ESLint analyzer on them with a custom configuration (eslint.config.js) that reflects the specifics of the vRO environment (e.g., recommending var instead of let, forbidding delete).
    3. It reports any errors and warnings.

// Snippet from eslint.config.js
'no-restricted-syntax': [
  'error',
  {
    selector: "VariableDeclaration[kind='let']",
    message: 'Use var or const instead of let.',
  },
  {
    selector: "UnaryExpression[operator='delete']",
    message: 'Avoid using delete; set the property to null instead.',
  },
],

4. docs-workflow.js – The Documentation Generator

This is the star of the show. This script aggregates all the information gathered from the XML file and an optional form definition file (_.json) to generate comprehensive documentation in Markdown format.

  • Purpose: To create a readable .md file for each workflow.
  • Key Elements of the Generated Documentation:
    • Workflow Details: Name, ID, version, description.
    • Tables: Clear lists of variables, inputs, and outputs.
    • Form Details: If a _.json file exists, the script parses it to document field labels, validation, default values, and other form properties.
    • Workflow Elements: A detailed description of each step, including its type, variable bindings, and embedded code.
    • Mermaid Diagram: An automatically generated flowchart diagram that visualizes the workflow’s logic, showing the connections between elements.

<!-- Example of a generated Mermaid diagram -->
```mermaid
flowchart LR
  Start["Start"]
  Script_Task["My Script Task"]
  Decision["Is it OK?"]
  End_Success["End Success"]
  End_Error["End Error"]

  Start --> Script_Task
  Script_Task --> Decision
  Decision -- "yes" --> End_Success
  Decision -- "no" --> End_Error

Orchestration with GitHub Actions

With these powerful tools in hand, we need a way to run them automatically. This is where GitHub Actions comes in.

The trigger-vro action provided in the prompt is one possible approach—it involves calling a dedicated workflow in vRO, which then handles the rest. This is a good solution if the logic must remain inside vRO.

However, there is an alternative, more GitHub-native approach that is fully self-contained and does not require communication with vRO during the documentation generation process. Below, I present a modified and complete action that performs the entire validation and documentation generation process directly on the GitHub runner.

.github/workflows/documenter.yml

name: Validate and Document vRO Workflows

on:
  pull_request:
    types: [opened, synchronize, reopened]
  push:
    branches:
      - main

jobs:
  build-and-validate:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: 'scripts/package.json' # Path to your package.json

      - name: Install dependencies
        run: npm install
        working-directory: ./scripts # Run in the scripts directory

      - name: Validate Naming and Descriptions
        run: node validate-workflow.js
        working-directory: ./scripts

      - name: Lint Embedded Scripts
        run: node lint-workflow.js
        working-directory: ./scripts

      # This step runs only on a push to the 'main' branch
      - name: Generate Markdown Documentation
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        run: node docs-workflow.js
        working-directory: ./scripts

      # Step to automatically commit the generated documentation
      - name: Commit documentation
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "docs: Auto-update workflow documentation"
          file_pattern: "docs/workflows/*.md" # File pattern to commit
          commit_user_name: "GitHub Actions Bot"
          commit_user_email: "github-actions@github.com"
          commit_author: "GitHub Actions Bot <github-actions@github.com>"

How does this action work?

  1. It triggers on every Pull Request and every push to the main branch.
  2. It sets up the Node.js environment and installs the necessary dependencies.
  3. On a Pull Request: It runs the validate-workflow.js and lint-workflow.js scripts. If either of them fails (e.g., due to a bad variable name), the entire action will fail, blocking the merge.
  4. On a Push to main: After a successful merge, the action runs the validation again and then generates the documentation using docs-workflow.js.
  5. Finally, it uses the git-auto-commit-action to automatically commit and push the generated .md files back to the repository.

Step-by-Step Implementation Guide

Want to implement this yourself? Here’s what you need to do:

  1. Repository Structure: Organize your files. It’s good practice to keep helper scripts in a separate directory.
.
├── .github/workflows/documenter.yml
├── scripts/
│   ├── docs-workflow.js
│   ├── lint-workflow.js
│   ├── parse-vro.js
│   ├── validate-workflow.js
│   ├── eslint.config.js
│   └── package.json  <-- Important file for dependencies!
├── workflows/
│   ├── My_Awesome_Workflow/
│   │   ├── workflow.xml
│   │   └── forms/
│   │       └── _.json
│   └── ...
└── docs/
    └── workflows/  <-- Generated documentation will go here
  1. Create package.json: In the scripts directory, create a package.json file to manage Node.js dependencies.
{
  "name": "vro-docs-scripts",
  "version": "1.0.0",
  "description": "Scripts for vRO workflow documentation and validation.",
  "type": "module",
  "dependencies": {
    "eslint": "^9.4.0",
    "fast-glob": "^3.3.2",
    "xml2js": "^0.6.2"
  }
}
  1. Copy the Scripts: Place all the provided .js files into the scripts directory.
  2. Add the GitHub Action: Create the .github/workflows/documenter.yml file and paste the YAML code above into it.
  3. Done! From now on, every change in your repository will undergo automatic quality control, and your documentation will always be up-to-date.

Summary

The solution presented here is a powerful step towards professionalizing your work with vRealize Orchestrator. Instead of relying on manual, outdated documentation, you gain a living, automatically maintained system that improves code quality, facilitates collaboration, and saves countless hours of work. It’s an investment that pays off almost immediately, making your automation processes more reliable and transparent than ever before.

P.S. For your convenience, all the scripts, configuration files, and the complete example from this article are available in my public Git repository here: https://github.com/vWorldLukasz/vmware

Share with:


Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • VCF Automation: From Zero to a Running Virtual Machine – A Step-by-Step Guide
  • Activating the Supervisor in VMware Cloud Foundation 9 with NSX VPC – A Step-by-Step Guide
  • Configuring an NSX Edge Cluster in VMware Cloud Foundation 9
  • Complete pfSense 2.7.2‑RELEASE configuration for a VMware Cloud Foundation 9 home lab
  • Automating vRO Workflow Documentation with GitHub Actions

Archives

Follow Me!

Follow Me on TwitterFollow Me on LinkedIn

GIT

  • GITHub – vWorld GITHub – vWorld 0
© 2025 vWorld | Powered by Superbs Personal Blog theme