{"_id":"@appollo-ui/sf-plugin-deploy-hooks","name":"@appollo-ui/sf-plugin-deploy-hooks","dist-tags":{"latest":"2.0.0"},"versions":{"2.0.0":{"name":"@appollo-ui/sf-plugin-deploy-hooks","version":"2.0.0","description":"SF CLI plugin that executes configurable bash scripts before and after deploy commands with AI-powered error analysis","author":{"name":"Matt Simonis"},"license":"MIT","homepage":"https://github.com/appollo-ui/sf-plugin-deploy-hooks#readme","repository":{"type":"git","url":"git+https://github.com/appollo-ui/sf-plugin-deploy-hooks.git"},"bugs":{"url":"https://github.com/appollo-ui/sf-plugin-deploy-hooks/issues"},"keywords":["salesforce","sf-cli","sfdx","plugin","deploy","hooks","pre-deploy","post-deploy","ci-cd","automation","ai-analysis","copilot","error-analysis"],"type":"commonjs","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"tsc","clean":"rm -rf lib","compile":"tsc","watch":"tsc --watch","prepublishOnly":"npm run clean && npm run build"},"dependencies":{"@oclif/core":"^4"},"devDependencies":{"@types/node":"^20","typescript":"^5"},"oclif":{"hooks":{"prerun":"./lib/hooks/prerun.js","postrun":"./lib/hooks/postrun.js"}},"engines":{"node":">=18.0.0"},"gitHead":"3b074b4fb85f497a16d7bc978628529b2c24541d","_id":"@appollo-ui/sf-plugin-deploy-hooks@2.0.0","_nodeVersion":"25.5.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-BAcnTfRZv6TR9N+CSsPV5A8PnkDhBVev0/58bLfhXR6Ue7RfUCM/NyVeyu9QErje9Jcwjisba4EryOdfgZt9Tg==","shasum":"755a2327e19ffe2fb153e03c9bbfc3f220aa398a","tarball":"https://registry.npmjs.org/@appollo-ui/sf-plugin-deploy-hooks/-/sf-plugin-deploy-hooks-2.0.0.tgz","fileCount":32,"unpackedSize":55746,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDPexQoPc1sZRq48t8QN2/1fFJdKwn/Pcm6gqBF3Pn7/gIhAJ68N1h6DuHZ/mN/1sY2S1HykU2oYMSZHPJAKOg7/DMr"}]},"_npmUser":{"name":"mattsimonis","email":"me@mattsimonis.com"},"directories":{},"maintainers":[{"name":"mattsimonis","email":"me@mattsimonis.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sf-plugin-deploy-hooks_2.0.0_1769990561829_0.5157526279112878"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-02T00:02:41.761Z","2.0.0":"2026-02-02T00:02:41.964Z","modified":"2026-02-02T00:02:42.143Z"},"maintainers":[{"name":"mattsimonis","email":"me@mattsimonis.com"}],"description":"SF CLI plugin that executes configurable bash scripts before and after deploy commands with AI-powered error analysis","homepage":"https://github.com/appollo-ui/sf-plugin-deploy-hooks#readme","keywords":["salesforce","sf-cli","sfdx","plugin","deploy","hooks","pre-deploy","post-deploy","ci-cd","automation","ai-analysis","copilot","error-analysis"],"repository":{"type":"git","url":"git+https://github.com/appollo-ui/sf-plugin-deploy-hooks.git"},"author":{"name":"Matt Simonis"},"bugs":{"url":"https://github.com/appollo-ui/sf-plugin-deploy-hooks/issues"},"license":"MIT","readme":"# SF CLI Deploy Hooks Plugin\n\nA Salesforce CLI plugin that executes configurable bash scripts before and after `sf project deploy` commands with AI-powered error analysis support.\n\n[![npm version](https://badge.fury.io/js/%40appollo-ui%2Fsf-plugin-deploy-hooks.svg)](https://www.npmjs.com/package/@appollo-ui/sf-plugin-deploy-hooks)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Features\n\n- ✅ **Pre-deploy hooks** - Run validation, tests, or checks before deployment\n- ✅ **Post-deploy hooks** - Execute cleanup, notifications, or analysis after deployment\n- ✅ **Deploy result analysis** - Access full deployment results in JSON format\n- ✅ **AI-powered error analysis** - Automatic error detection and fix suggestions with GitHub Copilot\n- ✅ **Configurable** - Simple JSON configuration for multiple hooks\n- ✅ **Non-blocking post-hooks** - Post-deploy failures won't affect your deployment\n- ✅ **Environment variables** - Access command context in your scripts\n\n## Installation\n\n### Install from npm\n\n```bash\nsf plugins install @appollo-ui/sf-plugin-deploy-hooks\n```\n\n### Install from source (development)\n\n```bash\ngit clone https://github.com/appollo-ui/sf-plugin-deploy-hooks.git\ncd sf-plugin-deploy-hooks\nnpm install\nnpm run build\nsf plugins link .\n```\n\n### Verify installation\n\n```bash\nsf plugins\n```\n\nYou should see `@appollo-ui/sf-plugin-deploy-hooks` in the list.\n\n## Configuration\n\nCreate a `.sfhooks.json` or `sf-hooks.json` file in your project root:\n\n```json\n{\n  \"hooks\": {\n    \"preDeploy\": [\n      \"./scripts/lint.sh\",\n      \"./scripts/test.sh\",\n      \"./scripts/pre-deploy-checks.sh\"\n    ],\n    \"postDeploy\": [\n      \"./scripts/notify-team.sh\",\n      \"./scripts/cleanup.sh\"\n    ]\n  }\n}\n```\n\n### Supported Commands\n\nHooks are triggered for these deploy commands:\n\n- `sf project deploy start`\n- `sf project deploy validate`\n- `sf project deploy quick`\n- `sf project deploy resume`\n\n## Usage\n\n### Pre-Deploy Hooks\n\nPre-deploy hooks run **before** the deploy command executes. If any hook fails (exits with non-zero status), the deploy is aborted.\n\nExample `scripts/lint.sh`:\n\n```bash\n#!/bin/bash\nset -e\n\necho \"🔧 Running linter for command: ${SF_COMMAND}\"\nnpm run lint\n\necho \"✅ Linting passed\"\n```\n\n### Post-Deploy Hooks\n\nPost-deploy hooks run **after** the deploy command completes successfully. Hook failures are logged as warnings but don't affect the deploy.\n\nExample `scripts/notify-team.sh`:\n\n```bash\n#!/bin/bash\nset -e\n\necho \"📢 Notifying team of deployment: ${SF_COMMAND}\"\ncurl -X POST https://hooks.slack.com/... -d '{\"text\":\"Deploy completed!\"}'\n\necho \"✅ Notification sent\"\n```\n\n### AI-Assisted Error Analysis with Copilot CLI\n\nUse Copilot CLI to automatically analyze deployment errors and suggest fixes:\n\nExample `scripts/ai-analyze-errors.sh`:\n\n```bash\n#!/bin/bash\nset -e\n\nif [ -z \"$SF_DEPLOY_RESULT_FILE\" ] || [ ! -f \"$SF_DEPLOY_RESULT_FILE\" ]; then\n  echo \"✅ No deploy result to analyze\"\n  exit 0\nfi\n\n# Check for jq\nif ! command -v jq &> /dev/null; then\n  echo \"⚠️  jq not installed, skipping AI analysis\"\n  exit 0\nfi\n\n# Check if deploy succeeded\nSUCCESS=$(jq -r '.result.success // false' \"$SF_DEPLOY_RESULT_FILE\")\n\nif [ \"$SUCCESS\" = \"true\" ]; then\n  echo \"✅ Deploy succeeded, no errors to analyze\"\n  exit 0\nfi\n\necho \"🤖 AI-powered error analysis starting...\"\necho \"\"\n\n# Parse component failures\njq -c '.result.details.componentFailures[]?' \"$SF_DEPLOY_RESULT_FILE\" | while read -r failure; do\n  COMPONENT=$(echo \"$failure\" | jq -r '.fullName')\n  COMPONENT_TYPE=$(echo \"$failure\" | jq -r '.componentType')\n  PROBLEM=$(echo \"$failure\" | jq -r '.problem')\n  LINE_NUM=$(echo \"$failure\" | jq -r '.lineNumber // \"unknown\"')\n  \n  echo \"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\"\n  echo \"❌ Error in: $COMPONENT ($COMPONENT_TYPE)\"\n  echo \"   Line: $LINE_NUM\"\n  echo \"   Error: $PROBLEM\"\n  echo \"\"\n  \n  # Find the file path based on component type\n  FILE_PATH=\"\"\n  case \"$COMPONENT_TYPE\" in\n    ApexClass)\n      FILE_PATH=\"force-app/main/default/classes/${COMPONENT}.cls\"\n      ;;\n    ApexTrigger)\n      FILE_PATH=\"force-app/main/default/triggers/${COMPONENT}.trigger\"\n      ;;\n    LightningComponentBundle)\n      FILE_PATH=\"force-app/main/default/lwc/${COMPONENT}/${COMPONENT}.js\"\n      ;;\n    AuraDefinitionBundle)\n      FILE_PATH=\"force-app/main/default/aura/${COMPONENT}/${COMPONENT}Controller.js\"\n      ;;\n    *)\n      echo \"   ⚠️  Unknown component type, skipping file analysis\"\n      continue\n      ;;\n  esac\n  \n  # Check if file exists\n  if [ ! -f \"$FILE_PATH\" ]; then\n    echo \"   ⚠️  File not found: $FILE_PATH\"\n    continue\n  fi\n  \n  echo \"🔍 Analyzing file: $FILE_PATH\"\n  echo \"\"\n  \n  # Use GitHub Copilot CLI to analyze the error\n  # The error context is provided in the prompt\n  gh copilot suggest \"Analyze this Salesforce $COMPONENT_TYPE file and fix the deployment error: '$PROBLEM' at line $LINE_NUM. File: $FILE_PATH\"\n  \n  echo \"\"\ndone\n\n# Analyze test failures separately\nTEST_FAILURES=$(jq -r '.result.details.runTestResult.failures // [] | length' \"$SF_DEPLOY_RESULT_FILE\")\n\nif [ \"$TEST_FAILURES\" -gt 0 ]; then\n  echo \"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\"\n  echo \"🧪 Test Failures Detected: $TEST_FAILURES\"\n  echo \"\"\n  \n  jq -c '.result.details.runTestResult.failures[]?' \"$SF_DEPLOY_RESULT_FILE\" | while read -r test_failure; do\n    TEST_CLASS=$(echo \"$test_failure\" | jq -r '.name')\n    TEST_METHOD=$(echo \"$test_failure\" | jq -r '.methodName')\n    TEST_MESSAGE=$(echo \"$test_failure\" | jq -r '.message')\n    \n    echo \"❌ Test: $TEST_CLASS.$TEST_METHOD\"\n    echo \"   Error: $TEST_MESSAGE\"\n    echo \"\"\n    \n    TEST_FILE=\"force-app/main/default/classes/${TEST_CLASS}.cls\"\n    \n    if [ -f \"$TEST_FILE\" ]; then\n      echo \"🔍 Analyzing test: $TEST_FILE\"\n      gh copilot suggest \"Fix this failing Salesforce Apex test. Test method: $TEST_METHOD. Error: $TEST_MESSAGE. File: $TEST_FILE\"\n      echo \"\"\n    fi\n  done\nfi\n\necho \"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\"\necho \"✅ AI analysis complete\"\n```\n\n**Configure it:**\n\n```json\n{\n  \"hooks\": {\n    \"postDeploy\": [\n      \"./scripts/ai-analyze-errors.sh\"\n    ]\n  }\n}\n```\n\nThis hook will:\n1. Detect deployment failures automatically\n2. Parse component and test errors from the deploy result\n3. Locate the relevant source files\n4. Use GitHub Copilot CLI to analyze each error and suggest fixes\n5. Provide context-aware AI assistance for debugging\n\n### Environment Variables\n\nAll hook scripts receive:\n\n| Variable | Description |\n|----------|-------------|\n| `SF_COMMAND` | The sf command being executed (e.g., `project:deploy:start`) |\n| `SF_DEPLOY_RESULT_FILE` | Path to JSON file containing deploy results (post-deploy hooks only) |\n\n### Analyzing Deploy Results\n\nPost-deploy hooks receive the full deploy result as a JSON file via the `SF_DEPLOY_RESULT_FILE` environment variable. This allows you to analyze errors, warnings, and deployment details.\n\nExample `scripts/analyze-errors.sh`:\n\n```bash\n#!/bin/bash\nset -e\n\nif [ -z \"$SF_DEPLOY_RESULT_FILE\" ]; then\n  echo \"⚠️  No deploy result file available\"\n  exit 0\nfi\n\necho \"📊 Analyzing deployment results...\"\n\n# Check if jq is installed for JSON parsing\nif ! command -v jq &> /dev/null; then\n  echo \"⚠️  jq not installed, showing raw result\"\n  cat \"$SF_DEPLOY_RESULT_FILE\"\n  exit 0\nfi\n\n# Extract deployment status\nSUCCESS=$(jq -r '.result.success // false' \"$SF_DEPLOY_RESULT_FILE\")\n\nif [ \"$SUCCESS\" = \"false\" ]; then\n  echo \"❌ Deploy failed!\"\n  \n  # Parse and display component failures\n  jq -r '.result.details?.componentFailures[]? | \"  - \\(.fullName): \\(.problemType) - \\(.problem)\"' \"$SF_DEPLOY_RESULT_FILE\"\n  \n  # Parse and display test failures\n  jq -r '.result.details?.runTestResult?.failures[]? | \"  - Test \\(.name): \\(.message)\"' \"$SF_DEPLOY_RESULT_FILE\"\n  \n  # Send to error tracking service\n  curl -X POST https://your-error-tracker.com/api/errors \\\n    -H \"Content-Type: application/json\" \\\n    -d @\"$SF_DEPLOY_RESULT_FILE\"\nelse\n  echo \"✅ Deploy succeeded!\"\n  \n  # Log success metrics\n  COMPONENTS=$(jq -r '.result.numberComponentsDeployed // 0' \"$SF_DEPLOY_RESULT_FILE\")\n  echo \"  📦 Deployed $COMPONENTS components\"\nfi\n```\n\nThe deploy result JSON structure includes:\n\n```json\n{\n  \"command\": \"project:deploy:start\",\n  \"argv\": [\"--target-org\", \"myorg\"],\n  \"timestamp\": \"2026-02-01T23:30:00.000Z\",\n  \"result\": {\n    \"success\": true,\n    \"status\": \"Succeeded\",\n    \"id\": \"0Af...\",\n    \"numberComponentsDeployed\": 5,\n    \"numberComponentsTotal\": 5,\n    \"details\": {\n      \"componentSuccesses\": [...],\n      \"componentFailures\": [...],\n      \"runTestResult\": {...}\n    }\n  }\n}\n```\n\n### Multiple Hooks\n\nHooks execute sequentially in the order specified in the config. Each hook must complete successfully before the next one runs.\n\n### Aborting a Deploy\n\nPre-deploy hooks can abort a deploy by exiting with non-zero status:\n\n```bash\nif [ ! -f \"required-file.txt\" ]; then\n    echo \"❌ Required file missing!\"\n    exit 1\nfi\n```\n\n## Backward Compatibility\n\nFor backward compatibility, if no config file exists, the plugin will look for `./hooks/pre-deploy.sh` and execute it as a pre-deploy hook (legacy behavior).\n\n## Uninstall\n\n```bash\nsf plugins uninstall @appollo-ui/sf-plugin-deploy-hooks\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Links\n\n- [npm package](https://www.npmjs.com/package/@appollo-ui/sf-plugin-deploy-hooks)\n- [GitHub repository](https://github.com/appollo-ui/sf-plugin-deploy-hooks)\n- [Issues](https://github.com/appollo-ui/sf-plugin-deploy-hooks/issues)\n\n## Development\n\n```bash\ncd local-dev/sf-plugin-deploy-hooks\n\n# Watch for changes\nnpm run watch\n\n# In another terminal, test the hooks\nsf project deploy start --dry-run\n```\n\n## Example Configuration\n\n### Basic Setup\n\n```json\n{\n  \"hooks\": {\n    \"preDeploy\": [\n      \"./scripts/validate-code.sh\",\n      \"./scripts/run-tests.sh\",\n      \"./scripts/check-dependencies.sh\"\n    ],\n    \"postDeploy\": [\n      \"./scripts/warm-cache.sh\",\n      \"./scripts/send-notifications.sh\",\n      \"./scripts/update-docs.sh\"\n    ]\n  }\n}\n```\n\n### Advanced: Error Analysis\n\nFor comprehensive deploy error analysis, see the example script at `examples/analyze-deploy-errors.sh`:\n\n```json\n{\n  \"hooks\": {\n    \"postDeploy\": [\n      \"./examples/analyze-deploy-errors.sh\"\n    ]\n  }\n}\n```\n\nThis example script demonstrates:\n- Parsing deployment success/failure status\n- Extracting component failures with error types\n- Analyzing test failures and code coverage issues\n- Formatting error reports for easy reading\n- Integration points for error tracking services\n\n### Advanced: AI-Powered Error Analysis 🤖\n\nUse GitHub Copilot CLI to automatically analyze errors and get AI-powered fix suggestions:\n\n```json\n{\n  \"hooks\": {\n    \"postDeploy\": [\n      \"./examples/ai-analyze-errors.sh\"\n    ]\n  }\n}\n```\n\n**Prerequisites:**\n- Install GitHub CLI: `brew install gh`\n- Install Copilot: `gh extension install github/gh-copilot`\n- Install jq: `brew install jq`\n\nThis will automatically:\n1. Detect all deployment failures\n2. Locate the problematic source files\n3. Ask GitHub Copilot to explain each error\n4. Provide AI-generated suggestions for fixes\n5. Show you exactly where to look in your code\n\n**Example output when a deploy fails:**\n```\n🤖 Starting AI-powered error analysis with GitHub Copilot...\n\n❌ Component Error: MyClass (ApexClass)\n   Location: Line 42\n   Error: Variable does not exist: myVariabel\n\n🔍 Analyzing: force-app/main/default/classes/MyClass.cls\n\n💬 Asking GitHub Copilot for help...\n[Copilot suggests: \"Typo detected - 'myVariabel' should be 'myVariable'\"]\n```\n","readmeFilename":"README.md","_rev":"1-5ac0c25b7245744a250cd063ddba9565"}