{"id":35013533,"url":"https://github.com/beyond-the-cloud-dev/cicd-template","last_synced_at":"2026-03-18T01:09:12.399Z","repository":{"id":329755261,"uuid":"1120540998","full_name":"beyond-the-cloud-dev/cicd-template","owner":"beyond-the-cloud-dev","description":"CICD Pipelines","archived":false,"fork":false,"pushed_at":"2025-12-21T14:41:03.000Z","size":19,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-31T06:53:19.012Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/beyond-the-cloud-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-21T12:46:56.000Z","updated_at":"2025-12-21T14:41:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/beyond-the-cloud-dev/cicd-template","commit_stats":null,"previous_names":["beyond-the-cloud-dev/cicd-template"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/beyond-the-cloud-dev/cicd-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyond-the-cloud-dev%2Fcicd-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyond-the-cloud-dev%2Fcicd-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyond-the-cloud-dev%2Fcicd-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyond-the-cloud-dev%2Fcicd-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/beyond-the-cloud-dev","download_url":"https://codeload.github.com/beyond-the-cloud-dev/cicd-template/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyond-the-cloud-dev%2Fcicd-template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30639047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-18T00:09:27.587Z","status":"ssl_error","status_checked_at":"2026-03-18T00:09:26.123Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-27T05:07:14.832Z","updated_at":"2026-03-18T01:09:12.390Z","avatar_url":"https://github.com/beyond-the-cloud-dev.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# CI/CD Templates for GitHub Actions\n\nCentral repository with reusable workflows for Salesforce and other projects.\n\n## 📋 Table of Contents\n\n- [Available Workflows](#available-workflows)\n- [How to Use](#how-to-use)\n- [Secrets Configuration](#secrets-configuration)\n- [Usage Examples](#usage-examples)\n- [Requirements](#requirements)\n- [Security Best Practices](#security-best-practices)\n\n## 🔄 Available Workflows\n\n### Salesforce CI (Full Pipeline)\n[.github/workflows/salesforce-ci.yml](.github/workflows/salesforce-ci.yml)\n\nComplete CI pipeline for Salesforce projects:\n- ✅ Scratch org creation\n- ✅ Code deployment\n- ✅ Apex test execution with detailed result parsing\n- ✅ Automatic PR comments with test results\n- ✅ Code coverage\n- ✅ Optional Codecov upload\n- ✅ Automatic cleanup\n\n### Salesforce CI with Build Step\n[.github/workflows/salesforce-ci-with-build.yml](.github/workflows/salesforce-ci-with-build.yml)\n\nCI pipeline for Salesforce projects that require build/compilation:\n- ✅ Node.js dependencies installation\n- ✅ Custom build command execution\n- ✅ Build artifact verification\n- ✅ Scratch org creation and deployment\n- ✅ Apex test execution with detailed result parsing\n- ✅ Automatic PR comments with test results\n- ✅ Code coverage and Codecov upload\n- ✅ Git submodule support\n- ✅ Automatic cleanup\n\n### Salesforce PMD Code Scanner\n[.github/workflows/salesforce-pmd-scanner.yml](.github/workflows/salesforce-pmd-scanner.yml)\n\nApex code quality scanning using PMD:\n- ✅ Static code analysis\n- ✅ Potential bug detection\n- ✅ Security best practices verification\n- ✅ Performance and code style checking\n- ✅ Report generation\n\n## 🚀 How to Use\n\n### Step 1: Add Workflow to Your Project\n\nCreate a `.github/workflows/ci.yml` file in your repository:\n\n```yaml\nname: CI\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  salesforce-ci:\n    uses: beyond-the-cloud-dev/cicd-template/.github/workflows/salesforce-ci.yml@main\n    with:\n      node-version: '20'\n      test-level: 'RunLocalTests'\n      upload-to-codecov: true\n      codecov-slug: ${{ github.repository }}\n    secrets:\n      SFDX_AUTH_URL_DEVHUB: ${{ secrets.SFDX_AUTH_URL_DEVHUB }}\n      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n```\n\n### Step 2: Configure Secrets\n\nAdd required secrets in your repository (Settings → Secrets and variables → Actions):\n\n**Required:**\n- `SFDX_AUTH_URL_DEVHUB` - Dev Hub authentication URL\n\n**Optional:**\n- `CODECOV_TOKEN` - Token for coverage upload (if using Codecov)\n\n## 🔐 Secrets Configuration\n\n### For Public Repositories\nYou can use Organization Secrets, which will be automatically available in all public repositories.\n\n### For Private Repositories (Free Plan)\nUnfortunately, GitHub's free plan doesn't provide Organization Secrets for private repositories. You must manually add secrets in each repository:\n\n1. Go to Settings → Secrets and variables → Actions\n2. Click \"New repository secret\"\n3. Add secrets with **exactly the same names** as in the template\n\n**Important:** Secret names must match! Repository secrets take precedence over Organization secrets.\n\n### How to Get SFDX_AUTH_URL_DEVHUB\n\n```bash\n# Log in to your Dev Hub\nsf org login web --alias DevHub --set-default-dev-hub\n\n# Display auth URL\nsf org display --verbose --target-org DevHub\n```\n\nCopy the `Sfdx Auth Url` value and add it as a secret.\n\n## 📚 Usage Examples\n\nAll examples are located in the [examples](./examples/) directory:\n\n### 1. Full CI with Tests and Codecov\n[examples/salesforce-ci.yml](./examples/salesforce-ci.yml)\n```yaml\njobs:\n  salesforce-ci:\n    uses: beyond-the-cloud-dev/cicd-template/.github/workflows/salesforce-ci.yml@main\n    with:\n      node-version: '20'\n      sf-cli-version: 'latest'  # or specific version like '2.0.0'\n      upload-to-codecov: true\n      codecov-slug: ${{ github.repository }}\n    secrets:\n      SFDX_AUTH_URL_DEVHUB: ${{ secrets.SFDX_AUTH_URL_DEVHUB }}\n      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n```\n\n### 2. CI with Build Step (for projects with build process)\n[examples/salesforce-ci-with-build.yml](./examples/salesforce-ci-with-build.yml)\n```yaml\njobs:\n  salesforce-ci:\n    uses: beyond-the-cloud-dev/cicd-template/.github/workflows/salesforce-ci-with-build.yml@main\n    with:\n      node-version: '20'\n      sf-cli-version: 'latest'\n      build-command: 'npm run package:build'  # Your build command\n      build-artifact-path: 'force-app'  # Path to built source\n      checkout-submodules: true  # If you use git submodules\n      upload-to-codecov: true\n      codecov-slug: ${{ github.repository }}\n    secrets:\n      SFDX_AUTH_URL_DEVHUB: ${{ secrets.SFDX_AUTH_URL_DEVHUB }}\n      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n```\n\n### 3. CI with PMD Code Quality Scanning\n[examples/salesforce-ci-with-sast.yml](./examples/salesforce-ci-with-sast.yml)\n```yaml\njobs:\n  code-quality:\n    uses: beyond-the-cloud-dev/cicd-template/.github/workflows/salesforce-pmd-scanner.yml@main\n\n  salesforce-ci:\n    uses: beyond-the-cloud-dev/cicd-template/.github/workflows/salesforce-ci.yml@main\n```\n\n## ⚙️ Configuration Parameters\n\n### Salesforce CI - Inputs\n\n| Parameter | Type | Default Value | Description |\n|----------|-----|------------------|------|\n| `node-version` | string | `'20'` | Node.js version |\n| `sf-cli-version` | string | `'latest'` | Salesforce CLI version (e.g., \"2.0.0\" or \"latest\") |\n| `scratch-org-duration` | number | `1` | Scratch org lifetime (days) |\n| `scratch-org-wait` | number | `30` | Scratch org creation timeout (min) |\n| `deploy-wait` | number | `30` | Deployment timeout (min) |\n| `test-wait` | number | `30` | Test timeout (min) |\n| `test-level` | string | `'RunLocalTests'` | Test level (RunLocalTests, RunAllTestsInOrg) |\n| `scratch-def-file` | string | `'config/project-scratch-def.json'` | Path to scratch org definition |\n| `upload-to-codecov` | boolean | `false` | Upload coverage to Codecov |\n| `codecov-slug` | string | `''` | Repository slug for Codecov (org/repo) |\n\n### Salesforce CI - Secrets\n\n| Secret | Required | Description |\n|--------|----------|------|\n| `SFDX_AUTH_URL_DEVHUB` | ✅ Yes | Dev Hub authentication URL |\n| `CODECOV_TOKEN` | ❌ No | Codecov token (only if upload-to-codecov=true) |\n\n### Salesforce CI with Build - Inputs\n\n| Parameter | Type | Default Value | Description |\n|----------|-----|------------------|------|\n| `node-version` | string | `'20'` | Node.js version |\n| `sf-cli-version` | string | `'latest'` | Salesforce CLI version (e.g., \"2.0.0\" or \"latest\") |\n| `scratch-org-duration` | number | `1` | Scratch org lifetime (days) |\n| `scratch-org-wait` | number | `30` | Scratch org creation timeout (min) |\n| `deploy-wait` | number | `30` | Deployment timeout (min) |\n| `test-wait` | number | `30` | Test timeout (min) |\n| `test-level` | string | `'RunLocalTests'` | Test level (RunLocalTests, RunAllTestsInOrg) |\n| `scratch-def-file` | string | `'config/project-scratch-def.json'` | Path to scratch org definition |\n| `upload-to-codecov` | boolean | `false` | Upload coverage to Codecov |\n| `codecov-slug` | string | `''` | Repository slug for Codecov (org/repo) |\n| `build-command` | string | **required** | Command to build/generate source (e.g., \"npm run build\") |\n| `build-artifact-path` | string | `'force-app'` | Path to the built source code directory |\n| `checkout-submodules` | boolean | `false` | Whether to checkout git submodules |\n\n### Salesforce CI with Build - Secrets\n\n| Secret | Required | Description |\n|--------|----------|------|\n| `SFDX_AUTH_URL_DEVHUB` | ✅ Yes | Dev Hub authentication URL |\n| `CODECOV_TOKEN` | ❌ No | Codecov token (only if upload-to-codecov=true) |\n\n### PMD Scanner - Inputs\n\n| Parameter | Type | Default Value | Description |\n|----------|-----|------------------|------|\n| `node-version` | string | `'20'` | Node.js version |\n| `pmd-version` | string | `'7.0.0'` | PMD version |\n| `ruleset` | string | `'ruleset.xml'` | Path to PMD ruleset file |\n| `source-path` | string | `'force-app'` | Path to source code |\n| `fail-on-violation` | boolean | `false` | Fail on violations |\n\n## 🖥️ Supported Systems\n\n- ✅ **Linux** (ubuntu-latest)\n- ✅ **macOS** (can change runner to `macos-latest`)\n- ✅ **Windows** (can change runner to `windows-latest`)\n\nTo use a different runner, you can override the workflow or create your own version.\n\n## 📝 Requirements\n\n- **Node.js 20+** (default, configurable)\n- **Salesforce CLI** (installed automatically)\n- **Dev Hub** with scratch org creation permissions\n- **Git** (for code checkout)\n\n**Note:** You don't need `package.json` or `package-lock.json` in your Salesforce projects. The workflow installs Salesforce CLI globally without requiring npm dependencies in your project.\n\n## 🔄 Updates\n\nWorkflows use the `@main` tag, so they will always fetch the latest version. If you want to use a specific version:\n\n```yaml\nuses: beyond-the-cloud-dev/cicd-template/.github/workflows/salesforce-ci.yml@v1.0.0\n```\n\n## 🔒 Security Best Practices\n\n### Understanding the Security Model\n\nWhen you make this repository **public**, the workflow code becomes visible to everyone, but this does **NOT** expose your secrets. Here's why:\n\n#### ✅ What is Safe (No Security Risk)\n\n1. **Secrets are NEVER exposed** in public repositories\n   - GitHub Secrets are encrypted and never visible in logs or code\n   - Even if someone forks your repository, they cannot access your secrets\n   - Workflow logs automatically redact secret values (shown as `***`)\n\n2. **Workflow code visibility is normal**\n   - Public reusable workflows are a standard GitHub feature\n   - Your workflow code doesn't contain sensitive data (only references to secrets)\n   - Anyone can see WHAT your workflow does, but not the SECRET VALUES\n\n3. **Organization-level protection**\n   - If this repository is in a GitHub Organization, you can configure access policies\n   - Settings → Actions → General → \"Access\" section\n   - Choose which repositories can use your reusable workflows\n\n#### ⚠️ Potential Risks and How to Mitigate\n\n1. **Malicious Pull Requests from Forks (PUBLIC REPOS ONLY)**\n   - **Risk**: In public repositories, anyone can fork and create a PR that might try to exfiltrate secrets\n   - **Mitigation**:\n     ```yaml\n     # In your calling repository's workflow:\n     on:\n       pull_request_target:  # DON'T use this with untrusted code!\n         # This gives PR access to secrets - dangerous!\n\n     # Instead, use:\n     on:\n       pull_request:  # ✅ SAFE - secrets not available to forks\n         # Forks won't have access to secrets\n     ```\n   - **Best Practice**: Require approval for workflows from first-time contributors\n     - Go to: Repository Settings → Actions → General\n     - Select \"Require approval for first-time contributors\"\n\n2. **Accidental Secret Logging**\n   - **Risk**: Someone might accidentally echo secrets in logs\n   - **Mitigation**:\n     - GitHub automatically redacts registered secrets\n     - Never use `set -x` or `echo` with secret variables\n     - Review workflow changes carefully\n\n3. **Scope of Access**\n   - **Risk**: Secrets have access to your entire Dev Hub\n   - **Mitigation**:\n     - Use dedicated CI/CD user with minimal permissions\n     - Create a separate Dev Hub user just for CI/CD\n     - Regularly rotate your `SFDX_AUTH_URL_DEVHUB`\n\n#### 🛡️ Recommended Security Configuration\n\n1. **Enable Branch Protection**\n   ```\n   Repository Settings → Branches → Add branch protection rule\n   ✅ Require pull request reviews before merging\n   ✅ Require status checks to pass before merging\n   ✅ Require linear history\n   ✅ Do not allow bypassing the above settings\n   ```\n\n2. **Configure Workflow Permissions**\n   ```\n   Repository Settings → Actions → General → Workflow permissions\n   ✅ Read repository contents permission (default)\n   ❌ Do NOT enable \"Read and write permissions\" unless needed\n   ```\n\n3. **Use Environment Secrets for Extra Protection**\n   - Create environments (e.g., \"production\", \"staging\")\n   - Add required reviewers for sensitive environments\n   - Store sensitive secrets at environment level, not repository level\n\n4. **Monitor Secret Usage**\n   - Regularly review Actions logs in your repositories\n   - Set up notifications for workflow failures\n   - Check for unusual workflow runs\n\n5. **For Organization Repositories**\n   ```\n   Organization Settings → Actions → General\n\n   \"Fork pull request workflows from outside collaborators\":\n   ✅ Require approval for first-time contributors who recently created account\n   ✅ Require approval for all outside collaborators\n   ```\n\n#### 📋 Security Checklist Before Making Repository Public\n\n- [ ] Remove any hardcoded credentials or tokens from code\n- [ ] Verify all sensitive data is in GitHub Secrets (not in code)\n- [ ] Enable branch protection on main branch\n- [ ] Set \"Require approval for first-time contributors\" in Actions settings\n- [ ] Review all workflow files for accidental secret exposure\n- [ ] Use dedicated CI/CD service account with minimal permissions\n- [ ] Document which secrets are required in README\n- [ ] Set up proper access policies if using GitHub Organization\n- [ ] Consider using environment-level secrets for sensitive operations\n\n#### ❓ Common Questions\n\n**Q: If someone forks my public repo, can they see my secrets?**\nA: No, secrets are never copied to forks. Each repository maintains its own secrets.\n\n**Q: Can malicious code in a PR access my secrets?**\nA: Not if you use `pull_request` trigger (recommended). Only use `pull_request_target` with extreme caution.\n\n**Q: What happens if I accidentally commit a secret to git?**\nA: Immediately:\n1. Revoke/rotate the secret in Salesforce\n2. Remove it from git history (use tools like `git filter-branch` or BFG Repo-Cleaner)\n3. Update the secret in GitHub Secrets\n\n**Q: Should I use a personal access token or SFDX Auth URL?**\nA: Use SFDX Auth URL for Salesforce. It's more secure and can be easily revoked.\n\n## 💡 Best Practices\n\n1. **Use `@main` for development**, `@v1.0.0` for production\n2. **Add secrets at organization level** for public repositories\n3. **Keep secret names consistent** across all repositories\n4. **Use dedicated CI/CD service accounts** with minimal required permissions\n5. **Enable branch protection** and require PR reviews\n6. **Regularly audit** workflow runs and secret usage\n7. **Rotate secrets periodically** as part of security hygiene\n\n## 🤝 Contributing\n\nHave an idea for a new workflow? Create a Pull Request!\n\n1. Fork this repository\n2. Create a branch for your workflow\n3. Add workflow in `.github/workflows/`\n4. Add example in `examples/`\n5. Update README.md\n6. Create a Pull Request\n\n## 📄 License\n\nMIT License - you can use this repository in your projects.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyond-the-cloud-dev%2Fcicd-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbeyond-the-cloud-dev%2Fcicd-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyond-the-cloud-dev%2Fcicd-template/lists"}