---
url: /salesforce-devops-starter-kit/blocks/sfdx-delete-scratch-org.md
description: Delete a scratch org to clean up after a pipeline run.
---

# 🗑️ SFDX Delete Scratch Org

This repository implements a simple GitHub composite action for deleting a Salesforce scratch org. It is the natural counterpart to [sfdx-create-scratch-org](https://github.com/svierk/sfdx-create-scratch-org) and is typically used as a cleanup step so that scratch orgs created during a CI run are released again, even if previous steps fail.

## Usage

The action pairs nicely with the `username` output of the create action and an `if: always()` condition to guarantee cleanup:

```yaml
# Least-privilege token: the workflow only reads the repository and talks to
# Salesforce via the CLI, it never writes back to GitHub.
permissions:
  contents: read

jobs:
  scratch-org-ci:
    name: Scratch Org CI
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v7.0.1
        with:
          persist-credentials: false # the GITHUB_TOKEN is not needed after the checkout - don't leave it in .git/config

      - name: Install SF CLI
        uses: svierk/sfdx-cli-setup@v1.1.3

      - name: Authorize DevHub
        uses: svierk/sfdx-login@v1.4.2
        with:
          sfdx-url: ${{ secrets.SFDX_AUTH_URL }}
          set-default-dev-hub: true
          alias: devhub

      - name: Create Scratch Org
        id: scratch
        uses: svierk/sfdx-create-scratch-org@v1.3.2
        with:
          target-dev-hub: devhub
          definition-file: config/project-scratch-def.json
          duration-days: 1

      - name: Deploy Metadata
        uses: svierk/sfdx-deploy@v1.2.2
        with:
          source-dir: force-app
          target-org: ${{ steps.scratch.outputs.username }}
          destructive-changes: false # a fresh scratch org has nothing to delete

      # ... run tests, etc. ...

      - name: Delete Scratch Org
        if: always() # release the org even when a previous step failed
        uses: svierk/sfdx-delete-scratch-org@v1.1.2
        with:
          target-org: ${{ steps.scratch.outputs.username }}
```

A few conventions the example follows and that are worth keeping in your own workflows:

* **Pin every `uses:` to an exact release tag** (`@v1.1.2`), not to a branch like `@main` and not to a floating major like `@v1`. An update then becomes an explicit, reviewable change - ideally raised automatically by [Dependabot](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot).
* **Declare `permissions:`** at workflow or job level. Creating and deleting a scratch org needs nothing but `contents: read`.
* **Keep secrets in `secrets`/`env`.** Hand them to an action via its inputs. Wherever you do fall back to a `run:` script, pass dynamic values in through `env:` instead of interpolating `${{ ... }}` directly into the shell command.

The following actions were also used in the example on this page:

* [SFDX CLI Setup](https://github.com/svierk/sfdx-cli-setup) | Installs the Salesforce CLI and related plugins
* [SFDX Login](https://github.com/svierk/sfdx-login) | Handles Salesforce login using a SFDX auth URL or a JSON web token (JWT)
* [SFDX Create Scratch Org](https://github.com/svierk/sfdx-create-scratch-org) | Creates the scratch org that this action deletes again - the natural counterpart of this action
* [SFDX Deploy](https://github.com/svierk/sfdx-deploy) | Deploys Salesforce metadata to a target org

## Inputs

| Name         | Required | Default | Description                                                                  |
| ------------ | -------- | ------- | ---------------------------------------------------------------------------- |
| `target-org` | no       |         | Username or alias of the scratch org to delete. Not required if the default org is set. |
| `step-summary` | no     | `true`  | Write a result section to the GitHub Actions [job summary](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary). Set to `false` to avoid collisions with a custom workflow summary. |

The action always runs with `--no-prompt`, so it never blocks the pipeline waiting for confirmation.

On success the action logs a confirmation with the deleted org and, unless `step-summary` is set to `false`, adds an entry to the [GitHub Step Summary](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary), so the cleanup result is visible directly in the run overview.

## References

The deletion option supported by this GitHub composite action can be found in the Salesforce CLI Command Reference here:

* [org delete scratch](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_org_commands_unified.htm#cli_reference_org_delete_scratch_unified)

## Releases

Latest release notes can be found on the [release page](https://github.com/svierk/sfdx-delete-scratch-org/releases).

## License

The scripts and documentation in this project are released under the [MIT License](https://github.com/svierk/sfdx-delete-scratch-org/blob/main/LICENSE).

***

➡️ **Full source & releases:** [svierk/sfdx-delete-scratch-org](https://github.com/svierk/sfdx-delete-scratch-org)
