diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml new file mode 100644 index 0000000..edc3a97 --- /dev/null +++ b/.github/workflows/test-action.yml @@ -0,0 +1,59 @@ +name: Test Action + +on: + push: + branches: [main, 'devin/**'] + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + test-dry-run: + name: Test Dry Run Mode + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Test sync operation (dry run) + uses: ./ + with: + devin-api-key: ${{ secrets.DEVIN_API_KEY || 'test-key' }} + directory: './test-playbooks' + dry-run: 'true' + recursive: 'true' + + test-validation: + name: Test Input Validation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Test with missing API key (should fail) + id: test-fail + continue-on-error: true + uses: ./ + with: + devin-api-key: '' + directory: './test-playbooks' + + - name: Verify failure + if: steps.test-fail.outcome != 'failure' + run: | + echo "Action should have failed with missing API key" + exit 1 + + test-list: + name: Test List Operation (Dry Run) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Test list operation + uses: ./ + with: + devin-api-key: ${{ secrets.DEVIN_API_KEY || 'test-key' }} + operation: 'list' + dry-run: 'true' diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..0caa5fb --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,342 @@ +# Deployment Guide + +This guide explains how to deploy and publish the Devin Playbook Sync GitHub Action. + +## Table of Contents + +- [Prerequisites](#prerequisites) +- [Local Testing](#local-testing) +- [Publishing to GitHub Marketplace](#publishing-to-github-marketplace) +- [Versioning Strategy](#versioning-strategy) +- [Release Process](#release-process) +- [Update Process](#update-process) + +## Prerequisites + +Before deploying the action, ensure you have: + +1. **Repository Access**: Write access to the `samfert-codeium/DEVIN-GITHUB-ACTIONS` repository +2. **Devin API Key**: For testing purposes +3. **Git Configured**: Your local git is set up with proper credentials + +## Local Testing + +### Method 1: Using act (Recommended) + +[act](https://github.com/nektos/act) allows you to run GitHub Actions locally: + +1. Install act: + ```bash + # macOS + brew install act + + # Linux + curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash + + # Windows + choco install act-cli + ``` + +2. Create a test workflow: + ```bash + mkdir -p .github/workflows + cat > .github/workflows/test.yml << 'EOF' + name: Test Action + on: push + jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./ + with: + devin-api-key: ${{ secrets.DEVIN_API_KEY }} + directory: './test-playbooks' + dry-run: 'true' + EOF + ``` + +3. Create test markdown files: + ```bash + mkdir -p test-playbooks + echo "# Test Playbook\nThis is a test playbook." > test-playbooks/test.md + ``` + +4. Run the action locally: + ```bash + act push -s DEVIN_API_KEY=your-api-key-here + ``` + +### Method 2: Testing in a Fork + +1. Fork the repository to your personal account +2. Add your Devin API key to the fork's secrets +3. Create a test workflow and push changes +4. Monitor the Actions tab to see results + +### Method 3: Direct Testing in Repository + +1. Create a feature branch: + ```bash + git checkout -b test/action-validation + ``` + +2. Add a test workflow: + ```bash + mkdir -p .github/workflows + cat > .github/workflows/test-action.yml << 'EOF' + name: Test Action + on: + push: + branches: [test/*] + jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Test sync operation + uses: ./ + with: + devin-api-key: ${{ secrets.DEVIN_API_KEY }} + directory: './test-playbooks' + dry-run: 'true' + - name: Test list operation + uses: ./ + with: + devin-api-key: ${{ secrets.DEVIN_API_KEY }} + operation: 'list' + EOF + ``` + +3. Push and verify the action runs correctly + +## Publishing to GitHub Marketplace + +### Step 1: Prepare for Release + +1. Ensure all files are in the repository: + - `action.yml` (metadata) + - `scripts/sync-playbooks.sh` (main script) + - `README.md` (documentation) + - `LICENSE` (if not already present) + +2. Make the script executable: + ```bash + chmod +x scripts/sync-playbooks.sh + ``` + +3. Commit all changes: + ```bash + git add action.yml scripts/ README.md DEPLOYMENT.md + git commit -m "Prepare action for initial release" + git push origin main + ``` + +### Step 2: Create a Release + +1. Create and push a version tag: + ```bash + git tag -a v1.0.0 -m "Initial release of Devin Playbook Sync Action" + git push origin v1.0.0 + ``` + +2. Create a major version tag for easier updates: + ```bash + git tag -a v1 -m "Version 1.x" + git push origin v1 + ``` + +3. Go to GitHub repository โ†’ Releases โ†’ Draft a new release + +4. Fill in the release details: + - **Tag**: Select `v1.0.0` + - **Title**: `v1.0.0 - Initial Release` + - **Description**: Include release notes (see template below) + - Check "Publish this Action to the GitHub Marketplace" + - Select primary category: "Automation" + - Add secondary category: "Publishing" + +5. Click "Publish release" + +### Release Notes Template + +```markdown +## ๐ŸŽ‰ Initial Release + +### Features +- โœจ Scan directories for Markdown files +- ๐Ÿ“ค Sync files as Devin playbooks via API +- ๐Ÿ”„ Support for all 5 Devin playbook operations (Create, List, Get, Update, Delete) +- ๐Ÿงช Dry-run mode for testing +- ๐Ÿ“Š Detailed outputs (playbook IDs, counts, results) +- ๐Ÿ”’ Secure API key handling via GitHub secrets + +### Supported Operations +- `sync` - Create playbooks from markdown files +- `list` - List all team playbooks +- `get` - Retrieve specific playbook +- `update` - Update existing playbook +- `delete` - Delete a playbook + +### Usage +See [README.md](./README.md) for complete usage instructions. + +### API Documentation +- [Devin API Reference](https://docs.devin.ai/api-reference/overview) +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +``` + +## Versioning Strategy + +Follow [Semantic Versioning](https://semver.org/): + +- **MAJOR** (v2.0.0): Breaking changes +- **MINOR** (v1.1.0): New features, backward compatible +- **PATCH** (v1.0.1): Bug fixes, backward compatible + +### Version Tags + +Users can reference the action in three ways: + +```yaml +# Specific version (recommended for production) +uses: samfert-codeium/DEVIN-GITHUB-ACTIONS@v1.0.0 + +# Major version (gets latest v1.x.x) +uses: samfert-codeium/DEVIN-GITHUB-ACTIONS@v1 + +# Latest (not recommended for production) +uses: samfert-codeium/DEVIN-GITHUB-ACTIONS@main +``` + +## Release Process + +### For New Features (Minor Version) + +1. Develop feature in a feature branch +2. Update README.md with new capabilities +3. Test thoroughly +4. Merge to main +5. Create new tags: + ```bash + git checkout main + git pull + git tag -a v1.1.0 -m "Add [feature name]" + git push origin v1.1.0 + + # Update major version tag + git tag -fa v1 -m "Update v1 to v1.1.0" + git push origin v1 --force + ``` +6. Create GitHub release with changelog + +### For Bug Fixes (Patch Version) + +1. Fix bug in a bugfix branch +2. Update tests if needed +3. Merge to main +4. Create new tags: + ```bash + git checkout main + git pull + git tag -a v1.0.1 -m "Fix [bug description]" + git push origin v1.0.1 + + # Update major version tag + git tag -fa v1 -m "Update v1 to v1.0.1" + git push origin v1 --force + ``` +5. Create GitHub release with bugfix notes + +### For Breaking Changes (Major Version) + +1. Plan and document breaking changes +2. Update README.md with migration guide +3. Test extensively +4. Merge to main +5. Create new tags: + ```bash + git checkout main + git pull + git tag -a v2.0.0 -m "Major version 2 with breaking changes" + git push origin v2.0.0 + git tag -a v2 -m "Version 2.x" + git push origin v2 + ``` +6. Create GitHub release with detailed migration guide + +## Update Process + +### Updating the Action Code + +1. Make changes to `action.yml` or `scripts/sync-playbooks.sh` +2. Update README.md if behavior changes +3. Test changes locally or in a feature branch +4. Follow the release process above + +### Updating Dependencies + +This action is self-contained and has minimal dependencies: +- **bash**: System default +- **curl**: Pre-installed on GitHub runners +- **jq**: Pre-installed on GitHub runners + +If you need to add dependencies: +1. Update the action to install them in a setup step +2. Document the new requirement in README.md +3. Test on all supported runner types (ubuntu-latest, macos-latest, windows-latest) + +## Best Practices + +### Before Publishing + +- [ ] Test all operation modes (sync, list, get, update, delete) +- [ ] Test with various directory structures +- [ ] Test error handling (invalid API key, network issues, etc.) +- [ ] Verify dry-run mode works correctly +- [ ] Check documentation is up-to-date +- [ ] Ensure scripts have proper permissions (`chmod +x`) +- [ ] Verify branding icons display correctly + +### After Publishing + +- [ ] Test the action using the marketplace version +- [ ] Monitor GitHub Issues for bug reports +- [ ] Update documentation based on user feedback +- [ ] Keep the action up-to-date with Devin API changes + +## Monitoring + +After deployment, monitor: + +1. **GitHub Insights**: Track action usage and popularity +2. **Issues & Discussions**: Respond to user questions and bug reports +3. **Devin API Changes**: Update action when API changes +4. **Security Advisories**: Address any security vulnerabilities promptly + +## Rolling Back + +If a release has critical issues: + +1. Update major version tag to previous working version: + ```bash + git tag -fa v1 -m "Rollback to v1.0.0" + git push origin v1 --force + ``` + +2. Create a new release explaining the rollback +3. Fix the issue and release a new patch version + +## Support + +For questions or issues: +- Open an issue in the repository +- Check existing documentation +- Review GitHub Actions logs for debugging + +## References + +- [GitHub Actions: Creating Actions](https://docs.github.com/en/actions/creating-actions) +- [Publishing Actions to Marketplace](https://docs.github.com/en/actions/creating-actions/publishing-actions-in-github-marketplace) +- [Devin API Documentation](https://docs.devin.ai/api-reference/overview) +- [Semantic Versioning](https://semver.org/) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..eb2815e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Sam Fertig + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 4b27438..b4272bb 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,36 @@ A collection of GitHub Actions for integrating with the Devin API. ## Available Actions +### Playbook Sync Action (Root) + +A GitHub Action that scans directories for Markdown files and syncs them as Devin playbooks using the Devin API. Supports all Devin playbook operations including create, list, get, update, and delete. + +๐Ÿ“– **Documentation**: See below for detailed usage instructions + +๐Ÿš€ **Quick Start**: + +```yaml +- name: Sync playbooks to Devin + uses: samfert-codeium/DEVIN-GITHUB-ACTIONS@v1 + with: + devin-api-key: ${{ secrets.DEVIN_API_KEY }} + directory: './playbooks' + operation: 'sync' +``` + +**Features:** +- ๐Ÿ“ Automatic discovery of `.md` files +- ๐Ÿ”„ Full API support for all 5 playbook operations (create, list, get, update, delete) +- ๐Ÿงช Dry run mode for testing +- ๐Ÿ“Š Detailed outputs with playbook IDs and counts + +**Supported Operations:** +- `sync` - Scan directory and create playbooks from `.md` files +- `list` - List all team playbooks +- `get` - Retrieve a specific playbook +- `update` - Update an existing playbook +- `delete` - Delete a playbook + ### Devin API Action A comprehensive GitHub Action for interacting with the Devin API to create and manage Devin sessions programmatically from your GitHub workflows. @@ -26,8 +56,7 @@ A comprehensive GitHub Action for interacting with the Devin API to create and m tags: 'bug-fix,automated' ``` -### Features - +**Features:** - **Session Management**: Create sessions, send messages, get status, list sessions - **File Operations**: Upload files to sessions - **Tagging**: Update session tags @@ -35,14 +64,16 @@ A comprehensive GitHub Action for interacting with the Devin API to create and m - **Knowledge Management**: Manage knowledge base entries - **Playbooks Management**: Create and manage playbooks -### Prerequisites +## Prerequisites 1. Get a Devin API key from your [Devin settings page](https://app.devin.ai/settings) 2. Store it as a GitHub secret (recommended name: `DEVIN_API_KEY`) -### Examples +## Examples + +See [devin-action/examples/](./devin-action/examples/) for Devin API Action workflow examples. -See [devin-action/examples/](./devin-action/examples/) for complete workflow examples. +See [test-playbooks/](./test-playbooks/) for example playbook markdown files. ## Contributing @@ -56,4 +87,5 @@ Contributions are welcome! Please feel free to submit a Pull Request. ## License -Apache-2.0 +- Playbook Sync Action: MIT License - see [LICENSE](./LICENSE) +- Devin API Action: Apache-2.0 diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..873d2a3 --- /dev/null +++ b/action.yml @@ -0,0 +1,132 @@ +name: 'Devin Playbook Sync' +description: 'Scans a directory for Markdown files and syncs them as Devin playbooks using the Devin API' +author: 'Sam Fertig (@samfert-codeium)' + +branding: + icon: 'book-open' + color: 'blue' + +inputs: + devin-api-key: + description: 'Devin API key for authentication. Can also be provided via DEVIN_API_KEY environment variable.' + required: true + + operation: + description: 'Operation to perform: sync, list, get, update, delete' + required: false + default: 'sync' + + directory: + description: 'Directory to scan for .md files (used with sync operation)' + required: false + default: '.' + + playbook-id: + description: 'Playbook ID (required for get, update, delete operations)' + required: false + default: '' + + playbook-title: + description: 'Title for the playbook (used with update operation)' + required: false + default: '' + + playbook-body: + description: 'Body/content for the playbook (used with update operation)' + required: false + default: '' + + playbook-macro: + description: 'Optional macro shortcut for the playbook (e.g., !deploy)' + required: false + default: '' + + api-base-url: + description: 'Base URL for the Devin API' + required: false + default: 'https://api.devin.ai' + + recursive: + description: 'Recursively scan subdirectories for .md files' + required: false + default: 'true' + + dry-run: + description: 'Run in dry-run mode without making actual API calls' + required: false + default: 'false' + +outputs: + playbook-ids: + description: 'Comma-separated list of created/updated playbook IDs' + value: ${{ steps.sync-playbooks.outputs.playbook-ids }} + + playbooks-count: + description: 'Number of playbooks processed' + value: ${{ steps.sync-playbooks.outputs.playbooks-count }} + + operation-result: + description: 'Result of the operation (JSON format)' + value: ${{ steps.sync-playbooks.outputs.operation-result }} + +runs: + using: 'composite' + steps: + - name: Validate inputs + shell: bash + run: | + echo "::group::Validating inputs" + + if [ -z "${{ inputs.devin-api-key }}" ]; then + echo "::error::devin-api-key is required" + exit 1 + fi + + OPERATION="${{ inputs.operation }}" + if [[ ! "$OPERATION" =~ ^(sync|list|get|update|delete)$ ]]; then + echo "::error::Invalid operation: $OPERATION. Must be one of: sync, list, get, update, delete" + exit 1 + fi + + if [[ "$OPERATION" =~ ^(get|update|delete)$ ]] && [ -z "${{ inputs.playbook-id }}" ]; then + echo "::error::playbook-id is required for $OPERATION operation" + exit 1 + fi + + if [[ "$OPERATION" == "update" ]] && [ -z "${{ inputs.playbook-title }}" ] && [ -z "${{ inputs.playbook-body }}" ]; then + echo "::error::Either playbook-title or playbook-body is required for update operation" + exit 1 + fi + + echo "โœ“ All inputs validated successfully" + echo "::endgroup::" + + - name: Setup environment + shell: bash + run: | + echo "::group::Setting up environment" + + # Create output directory for temporary files + mkdir -p "${{ runner.temp }}/devin-playbooks" + + echo "โœ“ Environment setup complete" + echo "::endgroup::" + + - name: Sync playbooks + id: sync-playbooks + shell: bash + env: + DEVIN_API_KEY: ${{ inputs.devin-api-key }} + API_BASE_URL: ${{ inputs.api-base-url }} + OPERATION: ${{ inputs.operation }} + DIRECTORY: ${{ inputs.directory }} + PLAYBOOK_ID: ${{ inputs.playbook-id }} + PLAYBOOK_TITLE: ${{ inputs.playbook-title }} + PLAYBOOK_BODY: ${{ inputs.playbook-body }} + PLAYBOOK_MACRO: ${{ inputs.playbook-macro }} + RECURSIVE: ${{ inputs.recursive }} + DRY_RUN: ${{ inputs.dry-run }} + TEMP_DIR: ${{ runner.temp }}/devin-playbooks + run: | + # Source the main script + "${{ github.action_path }}/scripts/sync-playbooks.sh" diff --git a/scripts/sync-playbooks.sh b/scripts/sync-playbooks.sh new file mode 100755 index 0000000..30a0a0f --- /dev/null +++ b/scripts/sync-playbooks.sh @@ -0,0 +1,311 @@ +#!/bin/bash + +set -e + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { + echo -e "${BLUE}โ„น${NC} $1" >&2 +} + +log_success() { + echo -e "${GREEN}โœ“${NC} $1" >&2 +} + +log_warning() { + echo -e "${YELLOW}โš ${NC} $1" >&2 +} + +log_error() { + echo -e "${RED}โœ—${NC} $1" >&2 +} + +api_call() { + local method="$1" + local endpoint="$2" + local data="$3" + local response_file="${TEMP_DIR}/api_response.json" + + local url="${API_BASE_URL}${endpoint}" + + if [ "$DRY_RUN" = "true" ]; then + log_warning "DRY RUN: Would call $method $url" + if [ -n "$data" ]; then + log_info "Request data: $data" + fi + echo '{"status":"dry-run","message":"Dry run mode - no actual API call made"}' + return 0 + fi + + local http_code + if [ -n "$data" ]; then + http_code=$(curl -s -w "%{http_code}" -o "$response_file" \ + -X "$method" \ + -H "Authorization: Bearer ${DEVIN_API_KEY}" \ + -H "Content-Type: application/json" \ + -d "$data" \ + "$url") + else + http_code=$(curl -s -w "%{http_code}" -o "$response_file" \ + -X "$method" \ + -H "Authorization: Bearer ${DEVIN_API_KEY}" \ + "$url") + fi + + if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then + cat "$response_file" + return 0 + else + log_error "API call failed with status $http_code" + cat "$response_file" >&2 + return 1 + fi +} + +create_playbook() { + local file_path="$1" + local title + local body + + title=$(basename "$file_path" .md) + body=$(cat "$file_path") + + log_info "Creating playbook: $title" + + local json_data + if [ -n "$PLAYBOOK_MACRO" ]; then + json_data=$(jq -n \ + --arg title "$title" \ + --arg body "$body" \ + --arg macro "$PLAYBOOK_MACRO" \ + '{title: $title, body: $body, macro: $macro}') + else + json_data=$(jq -n \ + --arg title "$title" \ + --arg body "$body" \ + '{title: $title, body: $body}') + fi + + local response + if response=$(api_call "POST" "/v1/playbooks" "$json_data"); then + local playbook_id + playbook_id=$(echo "$response" | jq -r '.playbook_id // .id // empty') + + if [ -n "$playbook_id" ]; then + log_success "Created playbook '$title' with ID: $playbook_id" + echo "$playbook_id" >> "${TEMP_DIR}/playbook_ids.txt" + else + log_warning "Playbook created but ID not found in response" + fi + return 0 + else + log_error "Failed to create playbook: $title" + return 1 + fi +} + +list_playbooks() { + log_info "Fetching all playbooks..." + + local response + if response=$(api_call "GET" "/v1/playbooks" ""); then + echo "$response" | jq '.' + + local count + count=$(echo "$response" | jq 'length // 0') + log_success "Found $count playbook(s)" + + echo "playbooks-count=$count" >> "$GITHUB_OUTPUT" + echo "operation-result<> "$GITHUB_OUTPUT" + echo "$response" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + return 0 + else + log_error "Failed to list playbooks" + return 1 + fi +} + +get_playbook() { + local playbook_id="$1" + log_info "Fetching playbook: $playbook_id" + + local response + if response=$(api_call "GET" "/v1/playbooks/${playbook_id}" ""); then + echo "$response" | jq '.' + log_success "Retrieved playbook: $playbook_id" + + echo "operation-result<> "$GITHUB_OUTPUT" + echo "$response" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + return 0 + else + log_error "Failed to get playbook: $playbook_id" + return 1 + fi +} + +update_playbook() { + local playbook_id="$1" + log_info "Updating playbook: $playbook_id" + + local title="$PLAYBOOK_TITLE" + local body="$PLAYBOOK_BODY" + + if [ -z "$title" ] && [ -z "$body" ]; then + log_error "Either title or body must be provided for update" + return 1 + fi + + if [ -z "$title" ] || [ -z "$body" ]; then + local current + if current=$(api_call "GET" "/v1/playbooks/${playbook_id}" ""); then + if [ -z "$title" ]; then + title=$(echo "$current" | jq -r '.title') + fi + if [ -z "$body" ]; then + body=$(echo "$current" | jq -r '.body') + fi + else + log_error "Failed to fetch current playbook for update" + return 1 + fi + fi + + local json_data + if [ -n "$PLAYBOOK_MACRO" ]; then + json_data=$(jq -n \ + --arg title "$title" \ + --arg body "$body" \ + --arg macro "$PLAYBOOK_MACRO" \ + '{title: $title, body: $body, macro: $macro}') + else + json_data=$(jq -n \ + --arg title "$title" \ + --arg body "$body" \ + '{title: $title, body: $body}') + fi + + local response + if response=$(api_call "PUT" "/v1/playbooks/${playbook_id}" "$json_data"); then + log_success "Updated playbook: $playbook_id" + + echo "operation-result<> "$GITHUB_OUTPUT" + echo "$response" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + return 0 + else + log_error "Failed to update playbook: $playbook_id" + return 1 + fi +} + +delete_playbook() { + local playbook_id="$1" + log_info "Deleting playbook: $playbook_id" + + local response + if response=$(api_call "DELETE" "/v1/playbooks/${playbook_id}" ""); then + log_success "Deleted playbook: $playbook_id" + + echo "operation-result<> "$GITHUB_OUTPUT" + echo "$response" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + return 0 + else + log_error "Failed to delete playbook: $playbook_id" + return 1 + fi +} + +sync_markdown_files() { + log_info "Scanning directory: $DIRECTORY" + + local find_cmd="find \"$DIRECTORY\" -type f -name '*.md'" + if [ "$RECURSIVE" != "true" ]; then + find_cmd="find \"$DIRECTORY\" -maxdepth 1 -type f -name '*.md'" + fi + + local md_files + md_files=$(eval "$find_cmd" | sort) + + if [ -z "$md_files" ]; then + log_warning "No .md files found in $DIRECTORY" + echo "playbooks-count=0" >> "$GITHUB_OUTPUT" + echo "playbook-ids=" >> "$GITHUB_OUTPUT" + return 0 + fi + + local total_files + total_files=$(echo "$md_files" | wc -l) + log_info "Found $total_files markdown file(s)" + + echo "::group::Creating playbooks" + + local success_count=0 + local failed_count=0 + + while IFS= read -r file; do + if [ -n "$file" ]; then + if create_playbook "$file"; then + success_count=$((success_count + 1)) + else + failed_count=$((failed_count + 1)) + fi + fi + done <<< "$md_files" + + echo "::endgroup::" + + log_success "Successfully created $success_count playbook(s)" + if [ $failed_count -gt 0 ]; then + log_warning "Failed to create $failed_count playbook(s)" + fi + + if [ -f "${TEMP_DIR}/playbook_ids.txt" ]; then + local ids + ids=$(cat "${TEMP_DIR}/playbook_ids.txt" | tr '\n' ',' | sed 's/,$//') + echo "playbook-ids=$ids" >> "$GITHUB_OUTPUT" + else + echo "playbook-ids=" >> "$GITHUB_OUTPUT" + fi + + echo "playbooks-count=$success_count" >> "$GITHUB_OUTPUT" +} + +main() { + echo "::group::Devin Playbook Sync - ${OPERATION}" + log_info "Starting operation: $OPERATION" + log_info "API Base URL: $API_BASE_URL" + + case "$OPERATION" in + sync) + sync_markdown_files + ;; + list) + list_playbooks + ;; + get) + get_playbook "$PLAYBOOK_ID" + ;; + update) + update_playbook "$PLAYBOOK_ID" + ;; + delete) + delete_playbook "$PLAYBOOK_ID" + ;; + *) + log_error "Unknown operation: $OPERATION" + exit 1 + ;; + esac + + echo "::endgroup::" + log_success "Operation completed successfully" +} + +main diff --git a/test-playbooks/code-review-checklist.md b/test-playbooks/code-review-checklist.md new file mode 100644 index 0000000..5bb1dd4 --- /dev/null +++ b/test-playbooks/code-review-checklist.md @@ -0,0 +1,54 @@ +# Code Review Checklist + +Use this playbook when reviewing pull requests to ensure consistent and thorough reviews. + +## Pre-Review + +- [ ] PR has a clear title and description +- [ ] All CI checks are passing +- [ ] No merge conflicts exist +- [ ] PR is not a draft + +## Code Quality + +- [ ] Code follows project style guidelines +- [ ] No unnecessary commented-out code +- [ ] No debug statements or console.logs +- [ ] Functions and variables have clear names +- [ ] Complex logic has explanatory comments +- [ ] No hardcoded values that should be constants + +## Functionality + +- [ ] Code does what the PR description says +- [ ] Edge cases are handled +- [ ] Error handling is appropriate +- [ ] No obvious bugs or logic errors +- [ ] Performance considerations addressed + +## Testing + +- [ ] New features have tests +- [ ] Tests cover edge cases +- [ ] All tests pass locally and in CI +- [ ] Test names clearly describe what they test + +## Documentation + +- [ ] README updated if needed +- [ ] API documentation updated +- [ ] Inline comments for complex logic +- [ ] Breaking changes documented + +## Security + +- [ ] No sensitive data in code +- [ ] Input validation present +- [ ] Authentication/authorization correct +- [ ] Dependencies are up to date + +## Final Steps + +- [ ] Leave constructive feedback +- [ ] Approve or request changes +- [ ] Follow up on previous review comments diff --git a/test-playbooks/example-setup.md b/test-playbooks/example-setup.md new file mode 100644 index 0000000..654e324 --- /dev/null +++ b/test-playbooks/example-setup.md @@ -0,0 +1,58 @@ +# Development Environment Setup + +This playbook guides you through setting up the development environment for our project. + +## Prerequisites + +Before starting, ensure you have: +- Git installed and configured +- Node.js 18 or higher +- Docker Desktop installed +- Access to the repository + +## Installation Steps + +1. Clone the repository: + ```bash + git clone https://github.com/org/repo.git + cd repo + ``` + +2. Install dependencies: + ```bash + npm install + ``` + +3. Copy environment variables: + ```bash + cp .env.example .env + ``` + +4. Configure your local environment: + - Update DATABASE_URL in .env + - Set API_KEY from the team secrets manager + - Configure any required service credentials + +5. Start the development server: + ```bash + npm run dev + ``` + +6. Verify the setup: + - Open http://localhost:3000 + - Run tests: `npm test` + - Check linting: `npm run lint` + +## Troubleshooting + +If you encounter issues: +- Clear node_modules and reinstall: `rm -rf node_modules && npm install` +- Verify Docker is running: `docker ps` +- Check Node version: `node --version` (should be 18+) + +## Next Steps + +After setup: +- Read the CONTRIBUTING.md guide +- Join the team Slack channel +- Attend the onboarding session