UNPKG

sf-agent-framework

Version:

AI Agent Orchestration Framework for Salesforce Development - Two-phase architecture with 70% context reduction

899 lines (735 loc) 21.4 kB
# Salesforce DevOps Tools ## Overview Salesforce DevOps tools enable continuous integration, continuous delivery, and automated deployment processes. This document provides a comprehensive guide to tools, platforms, and best practices for implementing DevOps in Salesforce environments. ## Native Salesforce Tools ### Salesforce CLI (sf) **Purpose**: Command-line interface for Salesforce development and deployment ```bash # Installation npm install -g @salesforce/cli # Version check sf --version # Key commands sf org login web --alias myorg sf project generate --name myproject sf project retrieve start --manifest package.xml sf project deploy start --target-org production sf apex test run --test-level RunLocalTests ``` **Configuration**: ```json // .sf/config.json { "target-org": "myorg", "target-dev-hub": "devhub", "apiVersion": "59.0", "disableTelemetry": false } ``` ### Salesforce DX **Purpose**: Source-driven development framework ```json // sfdx-project.json { "packageDirectories": [ { "path": "force-app", "default": true, "package": "MyPackage", "versionName": "Version 1.0", "versionNumber": "1.0.0.NEXT" } ], "namespace": "", "sourceApiVersion": "59.0", "packageAliases": { "MyPackage": "0Ho5e000000CaS1CAK" } } ``` ### DevOps Center **Purpose**: Native Salesforce DevOps platform **Features**: - Work item tracking - Pipeline management - Environment management - Release orchestration **Setup**: ```apex // Enable DevOps Center public class DevOpsCenterSetup { public static void enableDevOpsCenter() { // Navigate to Setup > DevOps Center // Enable and configure // Connect source control // Define pipelines } } ``` ## Version Control Systems ### Git Integration **GitHub**: ```yaml # .github/workflows/salesforce.yml name: Salesforce CI/CD on: push: branches: [main, develop] pull_request: branches: [main] jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: '18' - name: Install Salesforce CLI run: npm install -g @salesforce/cli - name: Authenticate run: | echo ${{ secrets.SFDX_AUTH_URL }} > auth.txt sf org login sfdx-url -f auth.txt -a ci-org - name: Deploy and Test run: | sf project deploy start --target-org ci-org --test-level RunLocalTests ``` **GitLab**: ```yaml # .gitlab-ci.yml stages: - validate - test - deploy variables: SALESFORCE_CLI_VERSION: 'latest' validate: stage: validate script: - npm install -g @salesforce/cli - echo $SFDX_AUTH_URL > auth.txt - sf org login sfdx-url -f auth.txt -a ci-org - sf project deploy validate --target-org ci-org test: stage: test script: - sf apex test run --target-org ci-org --wait 10 - sf apex test report --target-org ci-org deploy: stage: deploy only: - main script: - sf project deploy start --target-org production ``` **Bitbucket**: ```yaml # bitbucket-pipelines.yml pipelines: default: - step: name: Validate script: - npm install -g @salesforce/cli - echo $SFDX_AUTH_URL > auth.txt - sf org login sfdx-url -f auth.txt -a ci-org - sf project deploy validate --target-org ci-org branches: main: - step: name: Deploy to Production deployment: production script: - sf project deploy start --target-org production ``` ## CI/CD Platforms ### Jenkins **Setup**: ```groovy // Jenkinsfile pipeline { agent any environment { SF_USERNAME = credentials('sf-username') SF_PASSWORD = credentials('sf-password') SF_INSTANCE_URL = 'https://login.salesforce.com' } stages { stage('Checkout') { steps { git branch: 'main', url: 'https://github.com/company/salesforce-repo.git' } } stage('Build') { steps { sh 'npm install' sh 'npm run lint' } } stage('Authenticate') { steps { sh ''' echo "Authenticating to Salesforce" sf org login username \ --username $SF_USERNAME \ --password $SF_PASSWORD \ --instance-url $SF_INSTANCE_URL \ --alias jenkins-org ''' } } stage('Validate') { steps { sh ''' sf project deploy validate \ --target-org jenkins-org \ --test-level RunLocalTests ''' } } stage('Deploy') { when { branch 'main' } steps { sh ''' sf project deploy start \ --target-org jenkins-org \ --test-level RunLocalTests ''' } } } post { always { publishHTML([ allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'test-results', reportFiles: 'test-results.html', reportName: 'Test Results' ]) } } } ``` ### Azure DevOps **Pipeline Configuration**: ```yaml # azure-pipelines.yml trigger: branches: include: - main - develop pool: vmImage: 'ubuntu-latest' variables: - group: Salesforce-Credentials stages: - stage: Build jobs: - job: Validate steps: - task: NodeTool@0 inputs: versionSpec: '18.x' - script: npm install -g @salesforce/cli displayName: 'Install Salesforce CLI' - script: | echo $(SFDX_AUTH_URL) > auth.txt sf org login sfdx-url -f auth.txt -a azdo-org displayName: 'Authenticate to Salesforce' - script: | sf project deploy validate \ --target-org azdo-org \ --test-level RunLocalTests displayName: 'Validate Deployment' - stage: Deploy condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) jobs: - deployment: Production environment: 'salesforce-production' strategy: runOnce: deploy: steps: - script: | sf project deploy start \ --target-org production \ --test-level RunLocalTests displayName: 'Deploy to Production' ``` ### CircleCI **Configuration**: ```yaml # .circleci/config.yml version: 2.1 orbs: salesforce: circleci/salesforce@2.0.0 jobs: validate: docker: - image: cimg/node:18.0 steps: - checkout - salesforce/install - salesforce/auth: auth-url: SFDX_AUTH_URL - salesforce/deploy: deploy-type: validate test-level: RunLocalTests deploy: docker: - image: cimg/node:18.0 steps: - checkout - salesforce/install - salesforce/auth: auth-url: SFDX_AUTH_URL_PROD - salesforce/deploy: deploy-type: deploy test-level: RunLocalTests workflows: version: 2 validate_and_deploy: jobs: - validate - deploy: requires: - validate filters: branches: only: main ``` ## Salesforce-Specific DevOps Tools ### Copado **Features**: - User story management - Automated deployments - Compliance and governance - Release management **Implementation**: ```apex // Copado integration public class CopadoIntegration { public static void createUserStory(String title, String criteria) { copado__User_Story__c story = new copado__User_Story__c( copado__User_Story_Title__c = title, copado__Acceptance_Criteria__c = criteria, copado__Status__c = 'Draft', copado__Project__c = getActiveProject() ); insert story; } public static void promoteUserStory(Id storyId, String targetEnv) { copado__Promotion__c promotion = new copado__Promotion__c( copado__User_Story__c = storyId, copado__Source_Org_Credential__c = getCurrentOrg(), copado__Destination_Org_Credential__c = getTargetOrg(targetEnv) ); insert promotion; } } ``` ### Gearset **Features**: - Comparison and deployment - CI/CD pipelines - Backup and recovery - Monitoring and alerts **API Integration**: ```javascript // Gearset API usage const axios = require('axios'); class GearsetClient { constructor(apiKey) { this.apiKey = apiKey; this.baseUrl = 'https://api.gearset.com/v1'; } async createDeployment(sourceOrg, targetOrg, metadata) { const response = await axios.post( `${this.baseUrl}/deployments`, { source: sourceOrg, target: targetOrg, metadata: metadata, testLevel: 'RunLocalTests', }, { headers: { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, } ); return response.data.deploymentId; } async getDeploymentStatus(deploymentId) { const response = await axios.get(`${this.baseUrl}/deployments/${deploymentId}`, { headers: { Authorization: `Bearer ${this.apiKey}`, }, }); return response.data.status; } } ``` ### AutoRABIT **Features**: - Version control integration - Automated testing - Code quality analysis - Rollback capabilities **Configuration**: ```xml <!-- AutoRABIT configuration file --> <autorabit-config> <version-control> <type>Git</type> <url>https://github.com/company/salesforce-repo</url> <branch>main</branch> </version-control> <deployment> <source>feature/new-feature</source> <target>UAT</target> <test-level>RunSpecifiedTests</test-level> <test-classes> <class>AccountTriggerTest</class> <class>OpportunityTriggerTest</class> </test-classes> </deployment> <quality-gates> <code-coverage>80</code-coverage> <pmd-violations>0</pmd-violations> <security-scan>enabled</security-scan> </quality-gates> </autorabit-config> ``` ## Code Quality Tools ### PMD for Salesforce **Setup**: ```xml <!-- pmd-ruleset.xml --> <?xml version="1.0"?> <ruleset name="Salesforce PMD Rules" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd"> <description>Salesforce Apex PMD Rules</description> <rule ref="category/apex/design.xml"> <exclude name="ExcessiveParameterList"/> </rule> <rule ref="category/apex/performance.xml"/> <rule ref="category/apex/security.xml"/> <rule ref="category/apex/bestpractices.xml"> <exclude name="ApexUnitTestClassShouldHaveAsserts"/> </rule> <rule ref="category/apex/codestyle.xml"> <exclude name="MethodNamingConventions"/> </rule> </ruleset> ``` **Integration**: ```bash # Run PMD analysis pmd check -d force-app/main/default/classes -R pmd-ruleset.xml -f text # CI integration npm install -g @salesforce/sfdx-scanner sf scanner run --target force-app --category "Design,Best Practices,Security" ``` ### ESLint for LWC **Configuration**: ```json // .eslintrc.json { "extends": ["@salesforce/eslint-config-lwc/recommended"], "rules": { "@lwc/lwc/no-async-await": "error", "@lwc/lwc/no-inner-html": "error", "@lwc/lwc/no-document-query": "error", "no-console": "warn", "no-debugger": "error" }, "overrides": [ { "files": ["*.test.js"], "env": { "jest": true } } ] } ``` ## Testing Tools ### Jest for LWC **Setup**: ```json // jest.config.js const { jestConfig } = require('@salesforce/sfdx-lwc-jest/config'); module.exports = { ...jestConfig, coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } }, testPathIgnorePatterns: [ '<rootDir>/node_modules/', '<rootDir>/test/jest-mocks/' ] }; ``` **Test Example**: ```javascript // accountList.test.js import { createElement } from 'lwc'; import AccountList from 'c/accountList'; import getAccounts from '@salesforce/apex/AccountController.getAccounts'; jest.mock('@salesforce/apex/AccountController.getAccounts', () => ({ default: jest.fn() }), { virtual: true }); describe('c-account-list', () => { afterEach(() => { jest.clearAllMocks(); }); it('displays accounts when data is returned', async () => { const mockAccounts = [ { Id: '001', Name: 'Test Account 1' }, { Id: '002', Name: 'Test Account 2' }, ]; getAccounts.mockResolvedValue(mockAccounts); const element = createElement('c-account-list', { is: AccountList, }); document.body.appendChild(element); await Promise.resolve(); const accountElements = element.shadowRoot.querySelectorAll('.account'); expect(accountElements.length).toBe(2); }); }); ``` ### Apex Test Automation ```apex // Test data factory @isTest public class TestDataFactory { public static List<Account> createAccounts(Integer count) { List<Account> accounts = new List<Account>(); for (Integer i = 0; i < count; i++) { accounts.add(new Account( Name = 'Test Account ' + i, BillingCity = 'San Francisco', Industry = 'Technology' )); } return accounts; } } // Automated test execution public class TestAutomation { @future public static void runTestsAsync(String className) { ApexTestQueueItem[] testItems = [ SELECT Id, Status, ApexClassId FROM ApexTestQueueItem WHERE ApexClass.Name = :className ]; if (testItems.isEmpty()) { enqueueTests(new List<String>{className}); } } public static void enqueueTests(List<String> classNames) { List<ApexClass> testClasses = [ SELECT Id FROM ApexClass WHERE Name IN :classNames ]; if (!testClasses.isEmpty()) { System.enqueueTestRun(testClasses); } } } ``` ## Deployment Tools ### SFDX Deployment Scripts ```bash #!/bin/bash # deploy.sh set -e ENVIRONMENT=$1 TEST_LEVEL=${2:-RunLocalTests} echo "Deploying to $ENVIRONMENT with test level $TEST_LEVEL" # Authenticate case $ENVIRONMENT in "sandbox") sf org login web --instance-url https://test.salesforce.com --alias deploy-org ;; "production") sf org login web --instance-url https://login.salesforce.com --alias deploy-org ;; *) echo "Unknown environment: $ENVIRONMENT" exit 1 ;; esac # Validate first echo "Running validation..." sf project deploy validate \ --target-org deploy-org \ --test-level $TEST_LEVEL \ --wait 30 if [ $? -eq 0 ]; then echo "Validation successful. Proceeding with deployment..." sf project deploy start \ --target-org deploy-org \ --test-level $TEST_LEVEL \ --wait 30 else echo "Validation failed. Aborting deployment." exit 1 fi echo "Deployment complete!" ``` ### Package Management ```json // package.json for Salesforce project { "name": "salesforce-project", "version": "1.0.0", "scripts": { "lint": "npm run lint:lwc && npm run lint:apex", "lint:lwc": "eslint force-app/main/default/lwc", "lint:apex": "sf scanner run --target force-app --format table", "test": "npm run test:unit && npm run test:apex", "test:unit": "sfdx-lwc-jest", "test:apex": "sf apex test run --test-level RunLocalTests --output-dir test-results", "prettier": "prettier --write \"force-app/**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", "validate": "sf project deploy validate --test-level RunLocalTests", "deploy:sandbox": "./scripts/deploy.sh sandbox", "deploy:production": "./scripts/deploy.sh production", "retrieve": "sf project retrieve start", "create:scratch": "sf org create scratch --definition-file config/project-scratch-def.json --alias scratch-org --duration-days 7" }, "devDependencies": { "@salesforce/eslint-config-lwc": "^3.2.3", "@salesforce/sfdx-lwc-jest": "^1.1.0", "eslint": "^8.11.0", "prettier": "^2.6.0" } } ``` ## Monitoring and Logging ### Application Monitoring ```apex // Custom deployment monitoring public class DeploymentMonitor { public static void logDeployment(String status, String details) { Deployment_Log__c log = new Deployment_Log__c( Status__c = status, Deployed_By__c = UserInfo.getUserId(), Deployment_Date__c = DateTime.now(), Details__c = details, Components_Deployed__c = getDeployedComponents() ); insert log; if (status == 'Failed') { sendAlertToDevOpsTeam(log); } } private static void sendAlertToDevOpsTeam(Deployment_Log__c log) { Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); email.setToAddresses(new List<String>{'devops@company.com'}); email.setSubject('Deployment Failed: ' + log.Id); email.setHtmlBody(buildEmailBody(log)); Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{email}); } } ``` ### Performance Monitoring ```javascript // Monitor deployment performance class DeploymentMetrics { constructor() { this.metrics = { startTime: null, endTime: null, componentsDeployed: 0, testsRun: 0, testsPassed: 0, codeCoverage: 0, }; } startDeployment() { this.metrics.startTime = new Date(); } endDeployment(results) { this.metrics.endTime = new Date(); this.metrics.duration = this.metrics.endTime - this.metrics.startTime; this.metrics.componentsDeployed = results.numberComponentsDeployed; this.metrics.testsRun = results.numberTestsCompleted; this.metrics.testsPassed = results.numberTestsCompleted - results.numberTestErrors; this.metrics.codeCoverage = results.totalCoverage; this.logMetrics(); } logMetrics() { console.log('Deployment Metrics:', JSON.stringify(this.metrics, null, 2)); // Send to monitoring service fetch('https://monitoring.company.com/api/deployments', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + process.env.MONITORING_API_KEY, }, body: JSON.stringify(this.metrics), }); } } ``` ## Best Practices ### DevOps Maturity Model | Level | Characteristics | Tools | | ------------------- | -------------------------------------- | ---------------------------- | | 1 - Manual | Manual deployments, no version control | Change Sets | | 2 - Version Control | Code in Git, manual deployments | Git + Change Sets | | 3 - CI/CD | Automated testing and deployment | Git + Jenkins/GitHub Actions | | 4 - Advanced | Full automation, quality gates | Git + CI/CD + Copado/Gearset | | 5 - Optimized | Predictive analytics, self-healing | AI-powered DevOps platforms | ### Tool Selection Criteria ```yaml tool_evaluation: criteria: - version_control_integration: required - deployment_automation: required - testing_support: required - rollback_capability: required - monitoring_and_reporting: important - cost_effectiveness: important - learning_curve: consider - community_support: consider scoring_matrix: native_tools: pros: ['Free', 'Direct integration', 'Salesforce support'] cons: ['Limited features', 'Manual configuration'] score: 7/10 enterprise_platforms: pros: ['Full features', 'Support', 'Compliance'] cons: ['Cost', 'Complexity'] score: 9/10 open_source: pros: ['Free', 'Customizable', 'Community'] cons: ['Setup complexity', 'Maintenance'] score: 6/10 ``` ## Additional Resources - [Salesforce DX Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/) - [DevOps Center Documentation](https://help.salesforce.com/s/articleView?id=sf.devops_center.htm) - [CI/CD for Salesforce Best Practices](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ci_cd.htm) - [Trailhead: Salesforce DevOps](https://trailhead.salesforce.com/content/learn/trails/build-devops-culture)