> For the complete documentation index, see [llms.txt](https://docs.flxbl.io/flxbl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flxbl.io/flxbl/codev/migrating/migrating-to-codev/from-github-actions.md).

# From GitHub Actions

A GitHub Actions pipeline that builds Salesforce with sfp looks the same across teams: a `push` (or `pull_request`) trigger starts a job, the job runs in the sfp container, authenticates a Dev Hub, and calls `sfp build`, `sfp install`, `sfp publish`, or `sfp release`. This is a Build Your Own (BYO) workflow, so it runs [sfp-pro](https://docs.flxbl.io/flxbl/sfp). This page maps that shape onto codev, workflow by workflow: what the server takes over and what you stop running in CI.

Read [Migrating to codev](/flxbl/codev/migrating/migrating-to-codev.md) first for the overall approach — connect the repository, then hand over one capability at a time. This page is the GitHub-Actions-specific detail.

## What your pipeline looks like today

A typical build-and-publish workflow triggers on push, runs each stage in a container pinned to the sfp image, authenticates on every job, and calls sfp directly:

```yaml
# .github/workflows/build-deploy-publish.yml (self-run)
on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: ${{ vars.SFP_IMAGE }}       # you pin and upgrade this
      credentials: { username: ..., password: ${{ secrets.REGISTRY_TOKEN }} }
    steps:
      - uses: actions/checkout@v5
      - name: Authenticate Dev Hub
        run: sf org login sfdx-url -f ./authfile -a devhub -d
      - name: Create packages
        run: sfp build -v devhub --diffcheck --buildnumber ${GITHUB_RUN_ID} --branch ${GITHUB_REF#refs/heads/}
      - uses: actions/upload-artifact@v6
        with: { name: artifacts, path: artifacts }

  deploy:
    needs: build
    container: { image: '${{ vars.SFP_IMAGE }}' }
    steps:
      - name: Authenticate Salesforce
        run: sf org login jwt --client-id ... --jwt-key-file server.key --username ...
      - name: Deploy
        run: sfp install -o sit --skipifalreadyinstalled

  Publish:
    needs: build
    container: { image: '${{ vars.SFP_IMAGE }}' }
    steps:
      - name: Publish artifacts
        run: sfp publish -d artifacts --npm --scope my-org --gittag --pushgittag
```

Alongside it, teams usually have a set of per-environment release workflows (`release-sit.yml`, `release-uat.yml`, `release-prod.yml`, …) that each pin `SFP_IMAGE` and run `sfp release -o <env>`, and a set of pool-preparation workflows running `sfp pool prepare`.

Everything in this model is yours to operate: the image tag, the registry credentials, the Dev Hub and JWT auth on every job, the artifact hand-off between jobs, and one workflow file per environment.

## What codev runs instead

Connecting the repository to sfp server (see [Step 1](/flxbl/codev/migrating/migrating-to-codev.md#step-1-connect-the-repository-to-sfp-server)) registers webhooks, so a merge notifies the server directly — no `push`-triggered workflow needed. The server then runs the build on its own image and produces a release candidate.

The three-job `build → deploy → publish` workflow above collapses into **build-on-merge**, which you turn on from **Workflow Settings** on the Builds page:

| Your workflow today                                           | On codev                                                                                                                                                 |
| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `push` trigger + `container: image: ${{ vars.SFP_IMAGE }}`    | Webhook from onboarding; the server runs on its own image — no tag to pin                                                                                |
| `sf org login` / JWT auth on every job                        | The server holds the org connections; no per-job auth in CI                                                                                              |
| `sfp build --diffcheck`                                       | [Build on merge](/flxbl/codev/ci-cd/overview.md) — the server detects impacted [domains](/flxbl/codev/ci-cd/overview-1.md#domains) and builds only those |
| `upload-artifact` / `download-artifact` between jobs          | The server carries artifacts through to the release candidate                                                                                            |
| `sfp publish`                                                 | The server publishes package metadata; builds appear on the [Builds](/flxbl/codev/ci-cd/overview.md) page                                                |
| `sfp release -o sit`, `-o uat`, `-o prod` (one workflow each) | [Release candidates and releases](/flxbl/codev/ci-cd/overview-1.md) — one flow, target environments chosen at release time                               |
| `sfp pool prepare` workflows                                  | [Server-managed pools](/flxbl/codev/pools/overview.md)                                                                                                   |

The work your `build` job did per merge shows up on the Builds page, grouped by domain, with no runner or image in your pipeline:

<figure><img src="/files/U0CRrbfw0GNWBqqHI4rH" alt="Builds page listing server-produced builds grouped by domain, with per-domain filtering"><figcaption><p>What replaces the <code>build</code> job: each merge's impacted domains are built by the server and listed here. Builds your own pipeline still produces appear on the same page, so you can compare during the move.</p></figcaption></figure>

You do not convert all of this at once. Turn on build-on-merge for one branch or one domain, confirm the server's build lands on the Builds page next to your existing pipeline's, then retire the corresponding jobs.

## Move one workflow at a time

A safe order for a live repository:

1. **Connect the repository** and set up the [GitHub](/flxbl/codev/integrations/source-control/github.md) integration. Nothing changes yet — the webhooks are registered but server builds are off.
2. **Enable server builds for one domain** using **Domain build scope** ([Step 2](/flxbl/codev/migrating/migrating-to-codev.md#step-2-turn-on-server-managed-builds-gradually)). Your `build-deploy-publish.yml` still runs for everything else.
3. **Compare.** The server's build for that domain appears on the Builds page beside your workflow's. When you trust it, remove that domain's build from your workflow — or, once every domain is on the server, delete the `build` job.
4. **Hand over releases.** Replace the per-environment `release-*.yml` workflows with [release candidates](/flxbl/codev/ci-cd/overview-1.md); target environments are chosen at release time instead of one workflow per environment.
5. **Hand over pools and validation.** Move `sfp pool prepare` workflows to [server-managed pools](/flxbl/codev/pools/overview.md) and PR validation to [review environments](/flxbl/codev/inspect/review-environments.md).

At each step the workflows you have not moved keep running exactly as before, and their builds still show on the Builds page — provided the sfp-pro CLI in those workflows is on the same release as the server (see [While you still run some builds yourself](/flxbl/codev/migrating/migrating-to-codev.md#while-you-still-run-some-builds-yourself)). If your pipeline pins an old `SFP_IMAGE`, bring that image current before you connect, so the builds it still produces report correctly to the server.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flxbl.io/flxbl/codev/migrating/migrating-to-codev/from-github-actions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
