{"_id":"@bearingpointsalesforce/cicd-builder","_rev":"4-ad4cbba7ba4144ab04c3978c8d41d137","name":"@bearingpointsalesforce/cicd-builder","dist-tags":{"latest":"0.9.3"},"versions":{"0.9.0":{"name":"@bearingpointsalesforce/cicd-builder","version":"0.9.0","_id":"@bearingpointsalesforce/cicd-builder@0.9.0","maintainers":[{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"}],"homepage":"https://github.com/bearingpoint-salesforce/CICDBuilder#readme","bugs":{"url":"https://github.com/bearingpoint-salesforce/CICDBuilder/issues"},"bin":{"sf-cicd":"src/bin.js"},"dist":{"shasum":"ae5fc4e86824a2a1ce4b6c853ad9b003acfc0abf","tarball":"https://registry.npmjs.org/@bearingpointsalesforce/cicd-builder/-/cicd-builder-0.9.0.tgz","fileCount":20,"integrity":"sha512-RFBjppfwJfvvNGzne5uM/67sV2UDM3naB3tF+bx+2d4NiC2YBju4C4BB+7x8nBJPuBlduqmw8UdnCNTp2ZllAA==","signatures":[{"sig":"MEQCIEfIlmBXOB2Ltyc5Ioi33iC/uvPzekquf+IgzXbzNqLAAiB9UJ+immbBIg1ktsu/VbqZV0B7HTbK4CGeykcVUOmg2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68040},"type":"module","engines":{"node":">=20.0.0"},"exports":"./src/index.js","gitHead":"5fff9348820827893125dd03757cce22156320ad","scripts":{"test":"node --experimental-vm-modules node_modules/.bin/jest"},"_npmUser":{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"},"repository":{"url":"git+https://github.com/bearingpoint-salesforce/CICDBuilder.git","type":"git"},"_npmVersion":"10.8.2","description":"Reusable Salesforce CI/CD step functions and pipeline runner.","directories":{},"_nodeVersion":"20.20.1","dependencies":{"xmlbuilder2":"^3.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","@jest/globals":"^29.7.0"},"_npmOperationalInternal":{"tmp":"tmp/cicd-builder_0.9.0_1774939383252_0.5212293725740591","host":"s3://npm-registry-packages-npm-production"}},"0.9.1":{"name":"@bearingpointsalesforce/cicd-builder","version":"0.9.1","_id":"@bearingpointsalesforce/cicd-builder@0.9.1","maintainers":[{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"}],"homepage":"https://github.com/bearingpoint-salesforce/CICDBuilder#readme","bugs":{"url":"https://github.com/bearingpoint-salesforce/CICDBuilder/issues"},"bin":{"sf-cicd":"src/bin.js"},"dist":{"shasum":"0972daaae679fa0045fea547af7e6da5347ed5c2","tarball":"https://registry.npmjs.org/@bearingpointsalesforce/cicd-builder/-/cicd-builder-0.9.1.tgz","fileCount":20,"integrity":"sha512-aoE2IUqx/x5jd2/ytnGOqi7ht8cphHWxEkTfIFqFmtmcSEXY35Q2XDm9Fb0Cj5BebLcDjTtFW3ytwvuJWM1mIg==","signatures":[{"sig":"MEUCIQC5OlMBY47upRGNHan4PrRdwnwJU2M/zECosYHB101jyAIgd/A91lQZDByhq5d0ijBfNj1DN8WyVidy7+NRQHvbBkM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68043},"type":"module","engines":{"node":">=20.0.0"},"exports":"./src/index.js","gitHead":"747c43ea612734a09348d87b03e0f6357c4a7539","scripts":{"test":"node --experimental-vm-modules node_modules/.bin/jest"},"_npmUser":{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"},"repository":{"url":"git+https://github.com/bearingpoint-salesforce/CICDBuilder.git","type":"git"},"_npmVersion":"10.8.2","description":"Reusable Salesforce CI/CD step functions and pipeline runner.","directories":{},"_nodeVersion":"20.20.1","dependencies":{"xmlbuilder2":"^3.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","@jest/globals":"^29.7.0"},"_npmOperationalInternal":{"tmp":"tmp/cicd-builder_0.9.1_1774939963991_0.0502054958908833","host":"s3://npm-registry-packages-npm-production"}},"0.9.2":{"name":"@bearingpointsalesforce/cicd-builder","version":"0.9.2","license":"MIT","_id":"@bearingpointsalesforce/cicd-builder@0.9.2","maintainers":[{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"}],"homepage":"https://github.com/bearingpoint-salesforce/CICDBuilder#readme","bugs":{"url":"https://github.com/bearingpoint-salesforce/CICDBuilder/issues"},"bin":{"sf-cicd":"src/bin.js"},"dist":{"shasum":"1094da6929a6c40668a0244bb9e260d5476dc1ee","tarball":"https://registry.npmjs.org/@bearingpointsalesforce/cicd-builder/-/cicd-builder-0.9.2.tgz","fileCount":21,"integrity":"sha512-N76GtXUcS+4l74yq7zWTS/Crfvyxg/kAm47WMtO96wX/9h1FmUiaC/ifZ9K/RmjQcFefy6uBrRzOZNWpVqduLw==","signatures":[{"sig":"MEQCIGUMGctdsKuwRcQ12b/68/aIk+nxtgTiNyCiWfj3CMkjAiBVEnoaeMSh0uNO1QZSMYdBAREcjEGAPy01h6GBL3MPDQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69142},"type":"module","engines":{"node":">=20.0.0"},"exports":"./src/index.js","gitHead":"35f775e2e2289b026b65b0f58ec5f7fb2d3259a8","scripts":{"test":"node --experimental-vm-modules node_modules/.bin/jest"},"_npmUser":{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"},"repository":{"url":"git+https://github.com/bearingpoint-salesforce/CICDBuilder.git","type":"git"},"_npmVersion":"10.8.2","description":"Reusable Salesforce CI/CD step functions and pipeline runner.","directories":{},"_nodeVersion":"20.20.1","dependencies":{"xmlbuilder2":"^3.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","@jest/globals":"^29.7.0"},"_npmOperationalInternal":{"tmp":"tmp/cicd-builder_0.9.2_1774940738927_0.02316776104484375","host":"s3://npm-registry-packages-npm-production"}},"0.9.3":{"name":"@bearingpointsalesforce/cicd-builder","version":"0.9.3","description":"Reusable Salesforce CI/CD step functions and pipeline runner.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/bearingpoint-salesforce/CICDBuilder.git"},"type":"module","exports":"./src/index.js","bin":{"sf-cicd-builder":"src/bin.js"},"engines":{"node":">=20.0.0"},"scripts":{"test":"node --experimental-vm-modules node_modules/.bin/jest"},"dependencies":{"xmlbuilder2":"^3.1.1"},"devDependencies":{"jest":"^29.7.0","@jest/globals":"^29.7.0"},"_id":"@bearingpointsalesforce/cicd-builder@0.9.3","gitHead":"200470cc48c44cd107fa117d72c1433a6ce33b5a","bugs":{"url":"https://github.com/bearingpoint-salesforce/CICDBuilder/issues"},"homepage":"https://github.com/bearingpoint-salesforce/CICDBuilder#readme","_nodeVersion":"20.20.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-SWf7KyeGbQsUqe9L7Eds1ivhhte3z5VsA1zTVjjb1qlcV3nqchz+6ISkXdHFTpxVdLVxYTutSXI0ebglIrh9Cg==","shasum":"a89462a7ddd07c67e595de7547197b3857c0e05d","tarball":"https://registry.npmjs.org/@bearingpointsalesforce/cicd-builder/-/cicd-builder-0.9.3.tgz","fileCount":21,"unpackedSize":69379,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIB7vSjlIRh6z426Qp30t4dMZ2VLD9CyBMa9IbLezOdaTAiAv4c4ej5+l4FeA/6VSQsPTP/TiyPSK9wi9R6jWSl96WQ=="}]},"_npmUser":{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"},"directories":{},"maintainers":[{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cicd-builder_0.9.3_1775126385755_0.5280066919260269"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-31T06:43:03.183Z","modified":"2026-04-02T10:39:46.099Z","0.9.0":"2026-03-31T06:43:03.393Z","0.9.1":"2026-03-31T06:52:44.145Z","0.9.2":"2026-03-31T07:05:39.082Z","0.9.3":"2026-04-02T10:39:45.934Z"},"bugs":{"url":"https://github.com/bearingpoint-salesforce/CICDBuilder/issues"},"license":"MIT","homepage":"https://github.com/bearingpoint-salesforce/CICDBuilder#readme","repository":{"type":"git","url":"git+https://github.com/bearingpoint-salesforce/CICDBuilder.git"},"description":"Reusable Salesforce CI/CD step functions and pipeline runner.","maintainers":[{"name":"svatasejkora","email":"svatopluk.sejkora@bearingpoint.com"}],"readme":"# CI/CD Builder\n\nA shared Node.js library that provides reusable Salesforce CI/CD pipeline steps as plain async functions, driven by JSON\nconfiguration files. Replace complex bash scripts and other approaches that are not clear. Its dependency is node, which\nis required for SF CLI as well. If you use the `loadData` step, the SFDMU plugin must also be installed\n(`sf plugins install sfdmu`).\n\n## 1. Quick Start\n\n```sh\n# Install dependencies\nnpm install\n\n# Run a pipeline\nnode src/bin.js <pipeline.json> <scratchOrgAlias>\n\n# Examples\nnode src/bin.js config/pipeline.validate.json myScratchOrg\nnode src/bin.js config/pipeline.scratch.json newDevOrg\n```\n\nThe scratch org alias is required. If the org already exists, the `createOrg` step will be skipped. The dev hub is\nalways taken from the sf CLI default configuration (`sf config set target-dev-hub=yourHub`).\n\n---\n\n## 2. Pipeline Files\n\nA pipeline file defines an ordered sequence of steps to execute. It is a JSON file placed in the `config/` directory\nalongside `ciconfig.json`.\n\n### 2.1 Structure\n\n```json\n{\n    \"pipeline\": \"pipelineName\",\n    \"steps\": [\n        { \"type\": \"stepType\", \"option\": \"value\" },\n        { \"type\": \"anotherStep\" }\n    ]\n}\n```\n\n| Property   | Required | Description                               |\n|------------|----------|-------------------------------------------|\n| `pipeline` | Yes      | Name of the pipeline (used in log output) |\n| `steps`    | Yes      | Ordered array of step objects to execute  |\n\nEach step must have a `type` property. Additional properties are step-specific options.\n\n### 2.2 Available Step Types\n\n| Step Type             | Description                                                                                                                                                                                        |\n|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `createOrg`           | Creates a new scratch org using the default dev hub. If an org with the given alias already exists, creation is skipped.                                                                           |\n| `deleteOrg`           | Deletes the scratch org.                                                                                                                                                                           |\n| `printOrgUrl`         | Prints the org login URL without opening a browser.                                                                                                                                                |\n| `executeApex`         | Executes anonymous apex scripts for a named phase defined in `ciconfig.json`.                                                                                                                      |\n| `runTests`            | Runs apex tests in the org. By default runs in parallel with automatic synchronous rerun of failures.                                                                                              |\n| `installPackages`     | Installs packages defined in `ciconfig.packageIds`.                                                                                                                                                |\n| `deploySource`        | Deploys source metadata to the org.                                                                                                                                                                |\n| `sortMetadata`        | Sorts metadata XML files (profiles, permission sets, muting permission sets, permission set groups) for consistent formatting.                                                                     |\n| `assignPermSets`      | Assigns permission sets from `ciconfig.permSets` to the default org user. Already assigned permission sets are skipped.                                                                            |\n| `assignPermSetGroups` | Assigns permission set groups from `ciconfig.permSetGroups` to the default org user. Polls for `PermissionSetGroup.Status = 'Updated'` before assigning (up to 10 attempts, 7.5s interval).        |\n| `assignProfile`       | Assigns a profile from `ciconfig.profile` to the default org user. Uses a temporary System Administrator user as a workaround because Salesforce does not allow users to change their own profile. |\n| `loadData`            | Loads data into the scratch org from CSV files using the SFDMU plugin.                                                                                                                             |\n| `displayLimits`       | Displays the org's API limits.                                                                                                                                                                     |\n\n#### 2.2.1 createOrg\n\nCreates a new scratch org using the default dev hub. If an org with the given alias already exists, creation is skipped.\n\n```json\n{\n    \"type\": \"createOrg\",\n    \"definitionFile\": \"config/project-scratch-def.json\",\n    \"ci\": true\n}\n```\n\n| Option              | Type    | Default                           | Description                                                                     |\n|---------------------|---------|-----------------------------------|---------------------------------------------------------------------------------|\n| `definitionFile`    | string  | `config/project-scratch-def.json` | Path to the scratch org definition file                                         |\n| `durationDays`      | number  | `30`                              | Number of days before the scratch org expires                                   |\n| `wait`              | number  | `60`                              | Minutes to wait for org creation to complete                                    |\n| `ci`                | boolean | `false`                           | CI mode: merges features/settings into definition file, suppresses manual steps |\n| `validateOrg`       | boolean | `false`                           | Run apex verification script after creation, retry if corrupted                 |\n| `validationTimeout` | number  | `30`                              | Seconds to wait before running org validation                                   |\n\n#### 2.2.2 deleteOrg\n\nDeletes the scratch org.\n\n```json\n{\n    \"type\": \"deleteOrg\"\n}\n```\n\nNo options. Uses the scratch org alias from the CLI argument.\n\n#### 2.2.3 printOrgUrl\n\nPrints the org login URL without opening a browser.\n\n```json\n{\n    \"type\": \"printOrgUrl\"\n}\n```\n\nNo options.\n\n#### 2.2.4 executeApex\n\nExecutes anonymous apex scripts for a named phase defined in `ciconfig.json`.\n\n```json\n{\n    \"type\": \"executeApex\",\n    \"phase\": \"setup\"\n}\n```\n\n| Option  | Type   | Required | Description                                                         |\n|---------|--------|----------|---------------------------------------------------------------------|\n| `phase` | string | Yes      | Key in `ciconfig.apexPhases` (e.g. `setup`, `postDeploy`, `verify`) |\n\n#### 2.2.5 runTests\n\nRuns apex tests in the org. By default, tests run in parallel. Any failed test classes are automatically rerun\nsynchronously to catch flaky failures caused by parallel execution. Set `parallel` to `false` to run all tests\nsynchronously in a single run.\n\n```json\n{\n    \"type\": \"runTests\",\n   \"testLevel\": \"RunLocalTests\",\n   \"parallel\": true\n}\n```\n\n| Option      | Type    | Default         | Description                                                                                              |\n|-------------|---------|-----------------|----------------------------------------------------------------------------------------------------------|\n| `testLevel` | string  | `RunLocalTests` | `RunLocalTests` or `RunAllTestsInOrg`                                                                    |\n| `parallel`  | boolean | `true`          | Run tests in parallel with automatic synchronous rerun of failures. Set to `false` for synchronous only. |\n\n#### 2.2.6 installPackages\n\nInstalls packages defined in `ciconfig.packageIds`.\n\n```json\n{\n    \"type\": \"installPackages\"\n}\n```\n\n| Option         | Type   | Default      | Description                |\n|----------------|--------|--------------|----------------------------|\n| `securityType` | string | `AdminsOnly` | `AdminsOnly` or `AllUsers` |\n\n#### 2.2.7 deploySource\n\nDeploys source metadata to the org.\n\n```json\n{\n    \"type\": \"deploySource\",\n    \"sourceDir\": \"force-app\",\n    \"ci\": true\n}\n```\n\n| Option      | Type    | Default | Description                                                           |\n|-------------|---------|---------|-----------------------------------------------------------------------|\n| `sourceDir` | string  | —       | Source directory to deploy (e.g. `force-app`)                         |\n| `checkOnly` | boolean | `false` | Validate only, do not deploy                                          |\n| `ci`        | boolean | `false` | Append `ciconfig.ciForceignore` paths to `.forceignore` before deploy |\n\n#### 2.2.8 sortMetadata\n\nSorts metadata XML files (profiles, permission sets, muting permission sets, permission set groups) for consistent\nformatting.\n\n```json\n{\n    \"type\": \"sortMetadata\",\n    \"directory\": \"force-app/main/default\"\n}\n```\n\n| Option      | Type   | Default                  | Description             |\n|-------------|--------|--------------------------|-------------------------|\n| `directory` | string | `force-app/main/default` | Root metadata directory |\n\n#### 2.2.9 assignPermSets\n\nAssigns permission sets from `ciconfig.permSets` to the default org user. Already assigned permission sets are skipped.\n\n```json\n{\n    \"type\": \"assignPermSets\"\n}\n```\n\nNo options. Reads from `ciconfig.permSets`.\n\n#### 2.2.10 assignPermSetGroups\n\nAssigns permission set groups from `ciconfig.permSetGroups` to the default org user. Polls for\n`PermissionSetGroup.Status = 'Updated'` before assigning (up to 10 attempts, 7.5s interval).\n\n```json\n{\n    \"type\": \"assignPermSetGroups\"\n}\n```\n\nNo options. Reads from `ciconfig.permSetGroups`.\n\n#### 2.2.11 assignProfile\n\nAssigns a profile from `ciconfig.profile` to the default org user. Uses a temporary System Administrator user as a\nworkaround because Salesforce does not allow users to change their own profile.\n\n```json\n{\n    \"type\": \"assignProfile\"\n}\n```\n\nNo options. Reads from `ciconfig.profile`.\n\n#### 2.2.12 loadData\n\nLoads data into the scratch org from CSV files using the [SFDMU](https://help.sfdmu.com) SF CLI plugin. The data\ndirectory must contain an `export.json` configuration file and CSV files named after sObject API names (e.g.\n`Account.csv`, `Contact.csv`). SFDMU handles relationship resolution, lookup matching, and bulk operations\nautomatically.\n\nRequires the SFDMU plugin: `sf plugins install sfdmu`\n\n```json\n{\n   \"type\": \"loadData\",\n   \"path\": \"data\"\n}\n```\n\n| Option | Type   | Default | Description                                           |\n|--------|--------|---------|-------------------------------------------------------|\n| `path` | string | `data`  | Directory containing `export.json` and CSV data files |\n\n#### 2.2.13 displayLimits\n\nDisplays the org's API limits.\n\n```json\n{\n    \"type\": \"displayLimits\"\n}\n```\n\nNo options.\n\n### 2.3 Example Pipelines\n\n#### 2.3.1 Validation pipeline — create scratch org, deploy, test, delete:\n\n```json\n{\n    \"pipeline\": \"validate\",\n    \"steps\": [\n        { \"type\": \"createOrg\", \"definitionFile\": \"config/project-scratch-def.json\", \"durationDays\": 1, \"ci\": true },\n        { \"type\": \"installPackages\" },\n        { \"type\": \"deploySource\", \"sourceDir\": \"force-app\", \"ci\": true },\n        { \"type\": \"runTests\", \"testLevel\": \"RunLocalTests\" },\n        { \"type\": \"deleteOrg\" }\n    ]\n}\n```\n\n#### 2.3.2 Scratch org setup pipeline — full setup for development:\n\n```json\n{\n    \"pipeline\": \"createScratch\",\n    \"steps\": [\n        {\n            \"type\": \"createOrg\",\n            \"definitionFile\": \"config/project-scratch-def.json\",\n            \"ci\": true,\n            \"validateOrg\": true\n        },\n        {\n            \"type\": \"installPackages\"\n        },\n        {\n            \"type\": \"deploySource\",\n            \"sourceDir\": \"force-app\"\n        },\n        {\n            \"type\": \"assignPermSets\"\n        },\n        {\n            \"type\": \"assignPermSetGroups\"\n        },\n        {\n            \"type\": \"assignProfile\"\n        },\n       {\n          \"type\": \"loadData\"\n        }\n    ]\n}\n```\n\n---\n\n## 3. Configuration File (ciconfig.json)\n\nThe `ciconfig.json` file lives in the `config/` directory alongside the pipeline files. It holds project-specific\nsettings consumed by the pipeline steps.\n\n### 3.1 Full Example\n\n```json\n{\n    \"projectName\": \"my-project\",\n    \"packageIds\": [\n        { \"id\": \"04t5p000000Gey6AAC\", \"name\": \"DLRS\", \"versionNumber\": \"x.y\" },\n        { \"id\": \"04t1n000002NZ6gAAG\" }\n    ],\n    \"apexPhases\": {\n        \"setup\": [\"scripts/apex/enableMarketingUser.apex\"],\n        \"postDeploy\": [\"scripts/apex/insertCustomSettings.apex\"],\n        \"verify\": [\"scripts/apex/verifyOrgFeatures.apex\"]\n    },\n    \"profile\": \"Custom_Sales\",\n    \"permSetGroups\": [\"Integration_Managers\", \"Standard_User_Access\"],\n    \"permSets\": [\"Custom_Edit_Permissions\"],\n    \"defaultUserFields\": {\n        \"Country\": \"Czechia\",\n        \"City\": \"Prague\",\n        \"TimeZoneSidKey\": \"Europe/Prague\"\n    },\n    \"ciForceignore\": [\n        \"Admin.profile\",\n        \"src/main/default/entitlementProcesses/basic_sla.entitlementProcess-meta.xml\"\n    ],\n    \"postCreateManualSteps\": {\n        \"apexOrgVerification\": \"scripts/apex/verifyOrgFeatures.apex\",\n        \"continueInstruction\": \"Please continue by running 'npm run sfci:init:postcreate'.\",\n        \"features\": [\n            {\n                \"name\": \"ContactsToMultipleAccounts\",\n                \"manualStepDescription\": \"Enable 'Allow users to relate a contact to multiple accounts' in Setup > Account Settings.\"\n            }\n        ],\n        \"settings\": {\n            \"accountSettings\": {\n                \"enableRelateContactToMultipleAccounts\": true\n            }\n        }\n    }\n}\n```\n\n### 3.2 Properties Overview\n\n| Property                | Type             | Required                        | Description                                                                                |\n|-------------------------|------------------|---------------------------------|--------------------------------------------------------------------------------------------|\n| `projectName`           | string           | Yes                             | A human-readable name for your Salesforce project, used in log output during org creation. |\n| `packageIds`            | array of objects | Yes (for `installPackages`)     | List of managed/unlocked packages to install into the scratch org.                         |\n| `apexPhases`            | object           | Yes (for `executeApex`)         | Map of phase name to array of apex script file paths, executed by `executeApex` steps.     |\n| `profile`               | string           | Yes (for `assignProfile`)       | Salesforce profile name to assign to the default scratch org user.                         |\n| `permSetGroups`         | array of strings | Yes (for `assignPermSetGroups`) | Permission set group developer names to assign to the default org user.                    |\n| `permSets`              | array of strings | Yes (for `assignPermSets`)      | Permission set API names to assign to the default org user.                                |\n| `defaultUserFields`     | object           | No                              | User field values to set on the scratch org admin user after creation.                     |\n| `ciForceignore`         | array of strings | No                              | Additional paths to append to `.forceignore` before deployment in CI mode.                 |\n| `postCreateManualSteps` | object           | No                              | Configuration for post-creation behaviour: CI auto-merge and local manual step display.    |\n\n### 3.3 Properties Reference\n\n---\n\n#### 3.3.1 `projectName`\n\n|              |             |\n|--------------|-------------|\n| **Type**     | string      |\n| **Required** | Yes         |\n| **Used by**  | `createOrg` |\n\nA human-readable name for your Salesforce project. This is used to identify the project during org creation and will\nappear in log output. The pipeline will fail early if this is missing, so make sure to set it before running any\npipeline.\n\n---\n\n#### 3.3.2 `packageIds`\n\n|              |                                  |\n|--------------|----------------------------------|\n| **Type**     | array of objects                 |\n| **Required** | Yes (for `installPackages` step) |\n| **Used by**  | `installPackages`                |\n\nThe list of managed or unlocked packages that need to be installed into the scratch org before you can work with it.\nThink of this as your project's package dependencies — things like DLRS, CPQ, or any custom packages your org relies on.\n\nEach entry must have an `id` (the package version ID starting with `04t`). You can optionally add `name` and\n`versionNumber` for clearer log output, but they don't affect installation.\n\n| Attribute       | Description                                                      | Example                |\n|-----------------|------------------------------------------------------------------|------------------------|\n| `id`            | Package version ID (required). Must start with `04t`.            | `\"04t5p000000Gey6AAC\"` |\n| `name`          | Human-readable package name (optional). Used in log output only. | `\"DLRS\"`               |\n| `versionNumber` | Package version number (optional). Used in log output only.      | `\"x.y\"`                |\n\n```json\n{\n   \"packageIds\": [\n      {\n         \"id\": \"04tXXXXXXXXXXXXXXX\",\n         \"name\": \"Package Name\",\n         \"versionNumber\": \"1.0\"\n      },\n      {\n         \"id\": \"04tYYYYYYYYYYYYYYY\"\n      }\n   ]\n}\n```\n\n---\n\n#### 3.3.3 `apexPhases`\n\n|              |                                                   |\n|--------------|---------------------------------------------------|\n| **Type**     | object (map of phase name to array of file paths) |\n| **Required** | Yes (for `executeApex` step)                      |\n| **Used by**  | `executeApex`                                     |\n\nDefines groups of anonymous apex scripts that should run at different points during the pipeline. Each phase is a named\ncollection of scripts — you choose when they run by placing `executeApex` steps in your pipeline and referencing the\nphase name.\n\nCommon phases include:\n\n- **setup** — scripts that need to run before anything is deployed (e.g. enabling features, setting up users)\n- **postDeploy** — scripts that depend on your deployed metadata (e.g. inserting custom settings, test data)\n- **verify** — scripts that validate the org is configured correctly after everything is done\n\nYou can define as many phases as you need with any names you want.\n\n| Attribute     | Description                                                                    | Example                                        |\n|---------------|--------------------------------------------------------------------------------|------------------------------------------------|\n| `<phaseName>` | Array of file paths to anonymous apex scripts. The key is any name you choose. | `\"setup\": [\"scripts/apex/enableFeature.apex\"]` |\n\n```json\n{\n   \"apexPhases\": {\n      \"setup\": [\n         \"scripts/apex/enableFeature.apex\"\n      ],\n      \"postDeploy\": [\n         \"scripts/apex/insertData.apex\",\n         \"scripts/apex/configureOrg.apex\"\n      ],\n      \"verify\": [\n         \"scripts/apex/verifyFeatures.apex\"\n      ]\n   }\n}\n```\n\n---\n\n#### 3.3.4 `profile`\n\n|              |                                |\n|--------------|--------------------------------|\n| **Type**     | string                         |\n| **Required** | Yes (for `assignProfile` step) |\n| **Used by**  | `assignProfile`                |\n\nThe name of the Salesforce profile to assign to the default scratch org user. By default, scratch org users get the\nSystem Administrator profile. If your project requires developers to work under a different profile (e.g. a custom sales\nprofile), specify it here.\n\nNote: Salesforce doesn't allow users to change their own profile, so the tool creates a temporary admin user behind the\nscenes to perform the switch.\n\n---\n\n#### 3.3.5 `permSetGroups`\n\n|              |                                      |\n|--------------|--------------------------------------|\n| **Type**     | array of strings                     |\n| **Required** | Yes (for `assignPermSetGroups` step) |\n| **Used by**  | `assignPermSetGroups`                |\n\nList of permission set group **developer names** to assign to the default scratch org user. These are the API names you\nsee in Setup, not the labels.\n\nThe tool automatically waits for each permission set group to reach `Status = 'Updated'` before assigning it, since\nSalesforce needs time to calculate the combined permissions after a deployment.\n\n---\n\n#### 3.3.6 `permSets`\n\n|              |                                 |\n|--------------|---------------------------------|\n| **Type**     | array of strings                |\n| **Required** | Yes (for `assignPermSets` step) |\n| **Used by**  | `assignPermSets`                |\n\nList of permission set names to assign to the default scratch org user. These are the API names of the permission sets.\n\nThe tool checks which permission sets are already assigned and skips them, so it's safe to re-run the pipeline without\ncausing duplicate assignment errors.\n\n---\n\n#### 3.3.7 `defaultUserFields`\n\n|              |             |\n|--------------|-------------|\n| **Type**     | object      |\n| **Required** | No          |\n| **Used by**  | `createOrg` |\n\nSalesforce user field values to set on the scratch org admin user right after creation. This prevents common errors like\n`FIELD_INTEGRITY_EXCEPTION` on the Country field, which happens when the default user has no country set and certain\nfeatures expect one.\n\nIf this property is absent, no user fields are updated. Add any standard User field name as a key with the desired\nvalue.\n\n| Attribute        | Description                                                             | Example                |\n|------------------|-------------------------------------------------------------------------|------------------------|\n| `<fieldName>`    | Any standard Salesforce User field name as key, with the desired value. | `\"Country\": \"Czechia\"` |\n| `Country`        | Country of the scratch org user.                                        | `\"Czechia\"`            |\n| `City`           | City of the scratch org user.                                           | `\"Prague\"`             |\n| `TimeZoneSidKey` | Timezone identifier for the scratch org user.                           | `\"Europe/Prague\"`      |\n\n```json\n{\n   \"defaultUserFields\": {\n      \"Country\": \"Czechia\",\n      \"City\": \"Prague\",\n      \"TimeZoneSidKey\": \"Europe/Prague\"\n   }\n}\n```\n\n---\n\n#### 3.3.8 `ciForceignore`\n\n|              |                                  |\n|--------------|----------------------------------|\n| **Type**     | array of strings                 |\n| **Required** | No                               |\n| **Used by**  | `deploySource` (when `ci: true`) |\n\nAdditional paths to append to `.forceignore` before deployment when running in CI mode. This is useful for metadata that\nexists in your repository but causes deployment failures in scratch orgs — for example, certain profiles or org-specific\nconfigurations.\n\nThese paths are only added when the `deploySource` step has `\"ci\": true`. When developers run locally without the `ci`\nflag, their `.forceignore` stays untouched.\n\n---\n\n#### 3.3.9 `postCreateManualSteps`\n\n|              |             |\n|--------------|-------------|\n| **Type**     | object      |\n| **Required** | No          |\n| **Used by**  | `createOrg` |\n\nConfiguration for what happens after a scratch org is created. This serves two purposes:\n\n1. **In CI mode** (`ci: true`): The `features` names and `settings` are automatically merged into the scratch org\n   definition file before creation, so the org gets the right configuration without manual intervention.\n\n2. **For local development** (no `ci` flag): The tool prints a coloured box with manual steps the developer needs to\n   perform in the org's Setup UI, since some features can't be enabled through the definition file alone.\n\n| Attribute             | Description                                                                                                                                                                                             | Example                                                                |\n|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|\n| `apexOrgVerification` | Path to an apex script that checks whether all required features were enabled correctly. Used when `validateOrg: true` — if the script detects errors, the org is deleted and re-created automatically. | `\"scripts/apex/verifyOrgFeatures.apex\"`                                |\n| `continueInstruction` | A message shown to developers after org creation, typically telling them what command to run next. Only shown outside CI mode.                                                                          | `\"Please continue by running 'npm run sfci:init:postcreate'.\"`         |\n| `features`            | List of features that need special handling. Each entry has a `name` (merged into the definition file in CI) and a `manualStepDescription` (shown to developers locally).                               | See sub-attributes below.                                              |\n| `settings`            | Salesforce settings to merge into the scratch org definition file in CI mode. Uses the same structure as `settings` in the definition file itself.                                                      | `{\"accountSettings\": {\"enableRelateContactToMultipleAccounts\": true}}` |\n\nEach entry in `features` has:\n\n| Attribute               | Description                                                                                                                                           | Example                                                                                        |\n|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|\n| `name`                  | Salesforce feature name — automatically added to the scratch org definition file when running in CI mode.                                             | `\"ContactsToMultipleAccounts\"`                                                                 |\n| `manualStepDescription` | Human-readable instructions for the developer on how to enable this feature manually in the org's Setup UI. Only shown when running locally (non-CI). | `\"Enable 'Allow users to relate a contact to multiple accounts' in Setup > Account Settings.\"` |\n\n---\n\n## 4. CI Integration\n\nInstall the package in your project, then call the CLI in your pipeline. CI stays thin — one command per\npipeline:\n\n```yaml\n# GitHub Actions\n-   run: npm install @bearingpointsalesforce/cicd-builder\n-   run: npx sf-cicd-builder config/pipeline.validate.json ci-${{ github.run_id }}\n```\n\n```yaml\n# GitLab CI\nscript:\n   - npm install @bearingpointsalesforce/cicd-builder\n   - npx sf-cicd-builder config/pipeline.validate.json ci-$CI_PIPELINE_ID\n```\n\n```yaml\n# Azure DevOps\n-   script: npm install @bearingpointsalesforce/cicd-builder\n-   script: npx sf-cicd-builder config/pipeline.validate.json ci-$(Build.BuildId)\n```\n\n---\n\n## 5. Consuming as a Dependency\n\nAdd the package to your project:\n\n```bash\nnpm install @bearingpointsalesforce/cicd-builder\n```\n\nThen run pipelines from the command line:\n\n```bash\n# Run a full pipeline\nnpx sf-cicd-builder config/pipeline.validate.json myScratchOrg\n\n# Different pipeline for scratch org setup\nnpx sf-cicd-builder config/pipeline.scratch.json newDevOrg\n```\n","readmeFilename":"README.md"}