Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
293 changes: 293 additions & 0 deletions .github/workflows/docs-update-recipe-ref.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
# Automatically updates the Recipe Reference Guide when recipe struct fields,
# validation rules, or schema constraints change between releases.
#
# Triggers: Manual (for testing) or on release (production)
# Testing: Use dry_run mode to review outputs without creating PRs
# See: documentation/automation/recipe-schema-tracking/TESTING.md

name: Update Recipe Documentation

on:
workflow_dispatch: # Manual trigger for testing
inputs:
old_version:
description: 'Previous version (e.g., v1.14.0). Leave empty to auto-detect.'
required: false
type: string
new_version:
description: 'New version (e.g., v1.15.0). Leave empty to use HEAD.'
required: false
type: string
dry_run:
description: 'Dry run mode - generate files but do not create PR'
required: false
type: boolean
default: true

# Uncomment to enable automatic triggering on releases
# release:
# types: [published]

permissions:
contents: write # Create branches and commit files
pull-requests: write # Create PRs

jobs:
update-docs:
name: Update Recipe Documentation
runs-on: ubuntu-latest

env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for version comparison
fetch-tags: true # Fetch all tags so we can checkout version tags

- name: Fetch upstream tags (for forks)
if: github.repository != 'block/goose'
run: |
# Add upstream remote and fetch tags (only needed when testing in forks)
git remote add upstream https://github.com/block/goose.git || git remote set-url upstream https://github.com/block/goose.git
git fetch upstream --tags --force
echo "✅ Fetched tags from upstream (fork mode)"
echo "Total tags available: $(git tag | wc -l)"

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq ripgrep

- name: Set up Node.js
uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # pin@v3
with:
node-version: '20'

- name: Install goose CLI
run: |
mkdir -p /home/runner/.local/bin
curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh \
| CONFIGURE=false GOOSE_BIN_DIR=/home/runner/.local/bin bash
echo "/home/runner/.local/bin" >> $GITHUB_PATH
goose --version

- name: Configure goose for CI
env:
GOOSE_PROVIDER: ${{ vars.GOOSE_PROVIDER || 'openai' }}
GOOSE_MODEL: ${{ vars.GOOSE_MODEL || 'gpt-4o' }}
run: |
mkdir -p ~/.config/goose
cat <<EOF > ~/.config/goose/config.yaml
GOOSE_PROVIDER: $GOOSE_PROVIDER
GOOSE_MODEL: $GOOSE_MODEL
keyring: false
EOF
echo "✅ Created goose config:"
cat ~/.config/goose/config.yaml

- name: Determine versions to compare
id: versions
env:
GH_TOKEN: ${{ github.token }}
INPUT_OLD_VERSION: ${{ github.event.inputs.old_version }}
INPUT_NEW_VERSION: ${{ github.event.inputs.new_version }}
EVENT_NAME: ${{ github.event_name }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
get_previous_release() {
gh release list --limit 2 --json tagName --jq '.[].tagName' | sed -n '2p'
}

if [ -n "$INPUT_OLD_VERSION" ]; then
OLD_VERSION="$INPUT_OLD_VERSION"
else
OLD_VERSION=$(get_previous_release)
fi

if [ -n "$INPUT_NEW_VERSION" ]; then
NEW_VERSION="$INPUT_NEW_VERSION"
elif [ "$EVENT_NAME" = "release" ]; then
NEW_VERSION="$RELEASE_TAG"
else
NEW_VERSION="HEAD" # For testing unreleased changes
fi

if [ -z "$OLD_VERSION" ] || [ -z "$NEW_VERSION" ]; then
echo "Error: Could not determine versions to compare"
exit 1
fi

echo "old_version=$OLD_VERSION" >> $GITHUB_OUTPUT
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "OLD_VERSION=$OLD_VERSION" >> $GITHUB_ENV
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV

echo "✅ Comparing $OLD_VERSION → $NEW_VERSION"

- name: Extract and compare schemas
id: extract
timeout-minutes: 15
working-directory: documentation/automation/recipe-schema-tracking
env:
GOOSE_REPO: ${{ github.workspace }}
run: |
set -o pipefail # Ensure pipeline failures are caught

mkdir -p output
./scripts/run-pipeline.sh "$OLD_VERSION" "$NEW_VERSION" 2>&1 | tee output/pipeline.log

HAS_CHANGES=$(jq -r '.has_changes' output/validation-changes.json)
echo "has_changes=$HAS_CHANGES" >> $GITHUB_OUTPUT

if [ "$HAS_CHANGES" = "false" ]; then
echo "✅ No changes detected"
else
echo "✅ Changes detected"
fi

- name: Update recipe-reference.md (AI synthesis)
if: steps.extract.outputs.has_changes == 'true'
timeout-minutes: 10
working-directory: documentation/automation/recipe-schema-tracking/output
env:
RECIPE_REF_PATH: ${{ github.workspace }}/documentation/docs/guides/recipes/recipe-reference.md
run: |
echo "🔍 Environment diagnostics:"
echo " GOOSE_PROVIDER: $GOOSE_PROVIDER"
echo " GOOSE_MODEL: $GOOSE_MODEL"
echo " OPENAI_API_KEY: ${OPENAI_API_KEY:0:8}..." # Show first 8 chars only
echo " RECIPE_REF_PATH: $RECIPE_REF_PATH"
echo " HOME: $HOME"
echo " PATH: $PATH"
echo ""
echo "📁 Goose config file:"
cat ~/.config/goose/config.yaml || echo "Config file not found!"
echo ""
echo "📁 Current directory:"
pwd
ls -la
echo ""
echo "🤖 Step 1: Running validation changes synthesis..."
goose run --recipe ../recipes/synthesize-validation-changes.yaml

echo ""
echo "🤖 Step 2: Applying changes to recipe-reference.md..."
goose run --recipe ../recipes/update-recipe-reference.yaml

- name: Upload automation outputs
if: always()
uses: actions/upload-artifact@v4
with:
name: recipe-docs-update-${{ steps.versions.outputs.old_version }}-to-${{ steps.versions.outputs.new_version }}
path: |
documentation/automation/recipe-schema-tracking/output/*.json
documentation/automation/recipe-schema-tracking/output/*.md
documentation/automation/recipe-schema-tracking/output/*.log
retention-days: 30

- name: Create Pull Request
if: |
steps.extract.outputs.has_changes == 'true' &&
(github.event.inputs.dry_run != 'true' || github.event_name == 'release')
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6
with:
branch: docs/auto-recipe-reference-${{ steps.versions.outputs.new_version }}
delete-branch: true

commit-message: |
docs: Update recipe reference for ${{ steps.versions.outputs.new_version }}

Automated update based on schema changes between ${{ steps.versions.outputs.old_version }} and ${{ steps.versions.outputs.new_version }}.

title: "docs: Update Recipe Reference Guide for ${{ steps.versions.outputs.new_version }}"
body: |
## Summary

This PR updates the Recipe Reference Guide based on schema and validation changes detected between **${{ steps.versions.outputs.old_version }}** and **${{ steps.versions.outputs.new_version }}**.

### Type of Change
- [x] Documentation

### AI Assistance
- [x] This PR was created or reviewed with AI assistance

#### 🤖 Automation Details

- **Workflow**: `docs-update-recipe-ref.yml`
- **Triggered by**: ${{ github.event_name }}
- **Previous version**: ${{ steps.versions.outputs.old_version }}
- **New version**: ${{ steps.versions.outputs.new_version }}

#### 📋 Changes Detected

Review the workflow artifacts for detailed change analysis:
- `validation-changes.json` - Structured diff of changes
- `validation-changes.md` - Human-readable change documentation
- `update-summary.md` - Summary of documentation updates applied

Download artifacts from the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).

### ✅ Review Checklist

- [ ] Verify all schema changes are accurately documented
- [ ] Check that examples are updated correctly
- [ ] Ensure validation rules are clearly explained
- [ ] Confirm no unintended changes were made
- [ ] Do changes require additional updates in this or other recipe topics?

### 🔗 Related

- Release: ${{ github.event.release.html_url || 'N/A' }}

---

*This PR was automatically generated by the Recipe Documentation Automation workflow.*

labels: |
documentation
automated
recipe-reference

- name: Workflow summary
if: always()
env:
OLD_VERSION: ${{ steps.versions.outputs.old_version }}
NEW_VERSION: ${{ steps.versions.outputs.new_version }}
HAS_CHANGES: ${{ steps.extract.outputs.has_changes }}
DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }}
run: |
echo "## 📊 Recipe Documentation Update Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version Comparison**: $OLD_VERSION → $NEW_VERSION" >> $GITHUB_STEP_SUMMARY
echo "**Changes Detected**: $HAS_CHANGES" >> $GITHUB_STEP_SUMMARY
echo "**Dry Run Mode**: $DRY_RUN" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "$HAS_CHANGES" = "true" ]; then
echo "### ✅ Documentation Updated" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The Recipe Reference Guide has been updated to reflect changes in $NEW_VERSION." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "$DRY_RUN" = "true" ]; then
echo "**Note**: Running in dry-run mode - no PR was created. Review the artifacts to see the generated changes." >> $GITHUB_STEP_SUMMARY
else
echo "A pull request has been created with the documentation updates." >> $GITHUB_STEP_SUMMARY
fi
else
echo "### ℹ️ No Changes Needed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "No recipe schema or validation changes were detected between $OLD_VERSION and $NEW_VERSION." >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📦 Artifacts" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Download the workflow artifacts to review:" >> $GITHUB_STEP_SUMMARY
echo "- Extracted schemas and validation structures" >> $GITHUB_STEP_SUMMARY
echo "- Change detection results" >> $GITHUB_STEP_SUMMARY
echo "- Human-readable change documentation" >> $GITHUB_STEP_SUMMARY
echo "- Documentation update summary" >> $GITHUB_STEP_SUMMARY
58 changes: 58 additions & 0 deletions documentation/automation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Documentation Automation

This directory contains automated pipelines for keeping goose documentation synchronized with code changes.

## Overview

Each automation project tracks specific types of changes and updates corresponding documentation:

| Project | Status | Tracks | Updates |
|---------|--------|--------|---------|
| [recipe-schema-tracking](./recipe-schema-tracking/) | ✅ Active | Recipe schema & validation rules | Recipe Reference Guide |
| cli-command-tracking | 🔮 Planned | CLI commands & options | CLI documentation |
| provider-tracking | 🔮 Planned | Supported AI providers | Provider documentation |
| extension-tracking | 🔮 Planned | Built-in extensions | Extension documentation |

## Architecture

Each automation project follows a consistent pattern:

```
project-name/
├── README.md # Project-specific documentation
├── TESTING.md # How to test this automation
├── config/ # Configuration files
├── scripts/ # Deterministic extraction/diff scripts
└── recipes/ # AI-powered synthesis/update recipes
```

### Design Principles

1. **Modular**: Each project is self-contained
2. **Testable**: Clear inputs/outputs at each stage
3. **Transparent**: Intermediate files can be inspected
4. **Reusable**: Common patterns across projects

### Hybrid Approach

- **Shell scripts**: Deterministic extraction and comparison
- **AI recipes**: Synthesis and documentation updates

## GitHub Actions Integration

Automation projects can be triggered via GitHub Actions workflows in `.github/workflows/`.

See individual project TESTING.md files for workflow usage.

## Adding New Automations

When creating a new automation project:

1. Create a subdirectory: `documentation/automation/your-project/`
2. Follow the standard structure (README, TESTING, config, scripts, recipes)
3. Create corresponding GitHub Actions workflow (if needed)
4. Update this README with the new project

## Questions?

For project-specific questions, see the README in each project directory.
5 changes: 5 additions & 0 deletions documentation/automation/recipe-schema-tracking/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Generated output files
output/

# macOS
.DS_Store
Loading
Loading