This guide explains how to integrate Rails Flow Map into your continuous integration and deployment pipelines.
Integrating Rails Flow Map into your CI/CD pipeline provides:
- Automatic documentation updates - Keep architecture docs in sync with code
- PR/MR reviews - Visualize architectural changes in pull requests
- Quality gates - Enforce architectural standards
- Historical tracking - Monitor architecture evolution over time
Create .github/workflows/rails-flow-map.yml:
name: Generate Architecture Documentation
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
generate-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1'
bundler-cache: true
- name: Generate architecture documentation
run: |
bundle exec rake flow_map:generate_all
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: architecture-docs
path: doc/flow_maps/name: Architecture Analysis
on:
pull_request:
types: [opened, synchronize]
jobs:
analyze-architecture:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Full history for comparison
- name: Checkout base branch
run: |
git fetch origin ${{ github.base_ref }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1'
bundler-cache: true
- name: Generate architecture diff
id: diff
run: |
# Analyze base branch
git checkout ${{ github.base_ref }}
bundle exec rake flow_map:analyze > base.json
# Analyze PR branch
git checkout ${{ github.head_ref }}
bundle exec rake flow_map:analyze > pr.json
# Generate diff
bundle exec rake flow_map:diff BASE=base.json CURRENT=pr.json FORMAT=markdown > diff.md
# Set output
echo "diff<<EOF" >> $GITHUB_OUTPUT
cat diff.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Comment PR
uses: actions/github-script@v6
with:
script: |
const diff = `${{ steps.diff.outputs.diff }}`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Architecture Impact Analysis\n\n${diff}`
});name: Weekly Architecture Report
on:
schedule:
- cron: '0 0 * * 0' # Every Sunday at midnight
workflow_dispatch: # Manual trigger
jobs:
generate-report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1'
bundler-cache: true
- name: Generate comprehensive report
run: |
bundle exec rake flow_map:generate_all
bundle exec rake flow_map:metrics > metrics.md
- name: Create pull request
uses: peter-evans/create-pull-request@v5
with:
commit-message: 'docs: update architecture documentation'
title: 'Weekly Architecture Documentation Update'
body: |
## Automated Architecture Update
This PR updates the architecture documentation based on the current codebase.
### Generated files:
- Architecture diagrams
- API documentation
- Metrics report
branch: docs/architecture-updateCreate .gitlab-ci.yml:
stages:
- analyze
- document
variables:
BUNDLE_PATH: vendor/bundle
before_script:
- apt-get update -qq && apt-get install -y nodejs
- bundle config set --local path 'vendor/bundle'
- bundle install -j $(nproc)
analyze_architecture:
stage: analyze
script:
- bundle exec rake flow_map:analyze
- bundle exec rake flow_map:metrics
artifacts:
reports:
junit: reports/architecture-analysis.xml
paths:
- doc/flow_maps/
expire_in: 1 week
generate_docs:
stage: document
script:
- bundle exec rake flow_map:generate_all
artifacts:
paths:
- doc/flow_maps/
- public/architecture.html
expire_in: 1 month
only:
- main
- developarchitecture_diff:
stage: analyze
script:
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- git checkout $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- bundle exec rake flow_map:analyze > base.json
- git checkout $CI_COMMIT_SHA
- bundle exec rake flow_map:analyze > current.json
- bundle exec rake flow_map:diff BASE=base.json CURRENT=current.json FORMAT=gitlab > architecture_diff.md
artifacts:
reports:
codequality: architecture_diff.json
expose_as: 'Architecture Changes'
paths:
- architecture_diff.md
only:
- merge_requestsCreate .circleci/config.yml:
version: 2.1
orbs:
ruby: circleci/ruby@2.0.0
jobs:
generate_architecture_docs:
docker:
- image: cimg/ruby:3.1
steps:
- checkout
- ruby/install-deps
- run:
name: Generate architecture documentation
command: |
bundle exec rake flow_map:generate_all
- store_artifacts:
path: doc/flow_maps
destination: architecture-docs
- run:
name: Generate metrics report
command: |
bundle exec rake flow_map:metrics > metrics_report.md
- store_artifacts:
path: metrics_report.md
workflows:
version: 2
analyze_and_document:
jobs:
- generate_architecture_docs:
filters:
branches:
only:
- main
- developversion: 2.1
jobs:
architecture_analysis:
docker:
- image: cimg/ruby:3.1
steps:
- checkout
- run:
name: Fetch base branch
command: |
git fetch origin main:main
- ruby/install-deps
- run:
name: Analyze architecture changes
command: |
# Analyze main branch
git checkout main
bundle exec rake flow_map:analyze > main_architecture.json
# Analyze current branch
git checkout $CIRCLE_BRANCH
bundle exec rake flow_map:analyze > current_architecture.json
# Generate comparison
bundle exec rake flow_map:diff \
BASE=main_architecture.json \
CURRENT=current_architecture.json \
FORMAT=html > architecture_changes.html
- store_artifacts:
path: architecture_changes.html
destination: architecture-changes
workflows:
version: 2
pr_analysis:
jobs:
- architecture_analysis:
filters:
branches:
ignore: mainCreate Jenkinsfile:
pipeline {
agent any
stages {
stage('Setup') {
steps {
script {
// Install Ruby dependencies
sh 'bundle install'
}
}
}
stage('Analyze Architecture') {
steps {
script {
sh 'bundle exec rake flow_map:analyze'
sh 'bundle exec rake flow_map:metrics > metrics.txt'
}
}
}
stage('Generate Documentation') {
steps {
script {
sh 'bundle exec rake flow_map:generate_all'
}
}
}
stage('Archive Results') {
steps {
archiveArtifacts artifacts: 'doc/flow_maps/**/*', fingerprint: true
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'doc/flow_maps',
reportFiles: 'index.html',
reportName: 'Architecture Documentation'
])
}
}
}
post {
always {
cleanWs()
}
}
}pipeline {
agent any
environment {
CHANGE_TARGET = "${env.CHANGE_TARGET ?: 'main'}"
}
stages {
stage('Checkout') {
steps {
checkout scm
script {
if (env.CHANGE_ID) {
sh "git fetch origin ${env.CHANGE_TARGET}:${env.CHANGE_TARGET}"
}
}
}
}
stage('Architecture Diff') {
when {
changeRequest()
}
steps {
script {
// Analyze base branch
sh """
git checkout ${env.CHANGE_TARGET}
bundle exec rake flow_map:analyze > base_architecture.json
"""
// Analyze PR branch
sh """
git checkout ${env.GIT_COMMIT}
bundle exec rake flow_map:analyze > pr_architecture.json
"""
// Generate diff
sh """
bundle exec rake flow_map:diff \
BASE=base_architecture.json \
CURRENT=pr_architecture.json \
FORMAT=html > architecture_diff.html
"""
}
}
}
stage('Publish Results') {
steps {
publishHTML([
reportDir: '.',
reportFiles: 'architecture_diff.html',
reportName: 'Architecture Changes'
])
// Comment on PR if using GitHub
script {
if (env.CHANGE_ID && env.GITHUB_TOKEN) {
sh """
bundle exec rake flow_map:comment_pr \
PR_NUMBER=${env.CHANGE_ID} \
DIFF_FILE=architecture_diff.html
"""
}
}
}
}
}
}Speed up builds by caching Ruby gems:
# GitHub Actions
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
# GitLab CI
cache:
paths:
- vendor/bundle
# CircleCI
- restore_cache:
keys:
- gem-cache-{{ checksum "Gemfile.lock" }}Run different analyses in parallel:
# GitHub Actions
jobs:
analyze-models:
runs-on: ubuntu-latest
steps:
- run: bundle exec rake flow_map:models
analyze-controllers:
runs-on: ubuntu-latest
steps:
- run: bundle exec rake flow_map:controllers
analyze-routes:
runs-on: ubuntu-latest
steps:
- run: bundle exec rake flow_map:routesPrevent memory issues on large codebases:
# config/initializers/rails_flow_map.rb
RailsFlowMap.configure do |config|
config.memory_limit = ENV.fetch('CI_MEMORY_LIMIT', '2GB')
config.analysis_timeout = ENV.fetch('CI_TIMEOUT', '300').to_i.seconds
endOnly generate docs when relevant files change:
# GitHub Actions
- name: Check for relevant changes
id: changes
uses: dorny/paths-filter@v2
with:
filters: |
ruby:
- 'app/**/*.rb'
- 'lib/**/*.rb'
- 'config/routes.rb'
- name: Generate docs
if: steps.changes.outputs.ruby == 'true'
run: bundle exec rake flow_map:generate_allStore and compare historical data:
# Store analysis results
- uses: actions/upload-artifact@v3
with:
name: architecture-${{ github.sha }}
path: architecture.json
retention-days: 90
# Download for comparison
- uses: actions/download-artifact@v3
with:
name: architecture-${{ github.event.before }}
path: previous/-
Out of Memory
# Increase memory limit env: RAILS_FLOW_MAP_MEMORY_LIMIT: 4GB
-
Timeout on Large Repos
# Increase timeout timeout-minutes: 30
-
Missing Dependencies
# Install system dependencies - run: apt-get update && apt-get install -y graphviz
-
Permission Issues
# Ensure write permissions - run: chmod +x bundle exec rake flow_map:generate
Enable verbose logging for troubleshooting:
env:
RAILS_FLOW_MAP_LOG_LEVEL: debug
RAILS_FLOW_MAP_VERBOSE: trueFor more examples and configurations, check the examples directory.