# CI

---

## Overview

Connect your GitHub Actions workflows to Fly once, and every push automatically publishes your artifacts and creates a release with full traceability.

Once your CI is connected, every push to your repository automatically:

- **Publishes artifacts** to your team's Fly Registry (npm packages, Docker images, Helm charts, etc.)
- **Creates a release** with full traceability from commit to artifact
- **Links everything together**: commits, pull requests, artifacts, and releases — all connected
- **Finds releases by content**, not just version numbers. Ask your coding agent *"what release contains this fix?"* and get an answer

Connect once, and it works for every push going forward.

---

## Connect your CI

Connect once. Every workflow run that produces an artifact automatically creates a release in Fly.

1. **Prompt your coding agent:**

   *"Start working with Fly"*

   Make sure the Fly App is running and your coding agent is connected.

2. **Review and merge the PR.**

   Fly scans your `.github/workflows/*.yml` files and opens a PR that includes:

   - **OIDC Permissions**

     ```yaml
     permissions:
       contents: read
       id-token: write
     ```

   - **Fly Action**

     ```yaml
     - uses: jfrog/fly-action@v1              # Setup Fly package managers
     ```

   - **Docker and Helm paths** — if your workflow uses Docker or Helm, Fly includes the registry path as `FLY_REGISTRY_SUBDOMAIN` so you can reference it in your `docker push`, `docker pull`, `helm push`, and `helm pull` commands.

   **Example — Docker workflow**

   ```yaml
   permissions:                              # Required for Fly OIDC authentication
     contents: read
     id-token: write

   jobs:
     build:
       runs-on: ubuntu-latest
       steps:
         - uses: actions/checkout@v6
         - uses: jfrog/fly-action@v1          # Setup Fly package managers
         - run: docker build -t ${{ env.FLY_REGISTRY_SUBDOMAIN }}/docker/my-app:${{ github.sha }} .
         - run: docker push ${{ env.FLY_REGISTRY_SUBDOMAIN }}/docker/my-app:${{ github.sha }}
   ```

   > [!NOTE]
   > **Prefer to edit the YAML yourself?** Add the OIDC permissions block and the Fly action step to your `.github/workflows/*.yml` files directly. Place the **permissions block** at the top level (after `on:` and before `jobs:`), and the **Fly action step** inside your job (before artifact operations like `npm publish` or `docker push`).

---

## Skip specific package managers from CI

By default, the Fly action configures every supported package manager on the runner. To skip specific ones, use the `ignore` input:

```yaml
- uses: jfrog/fly-action@v1
  with:
    ignore: docker,pip
```

---

## Upload & download generic artifacts

Upload and download files that aren't standard packages (binaries, archives, test results) to and from Fly. After the Fly action step in your workflow, add the upload or download action with a package name, version, and the files to include.

**Upload:**

```yaml
- uses: jfrog/fly-action/upload@v1
  with:
    name: my-app
    version: '1.0.0'
    files: |
      dist/app.zip
      dist/app.tar.gz
```

**Download:**

```yaml
- uses: jfrog/fly-action/download@v1
  with:
    name: my-app
    version: '1.0.0'
    files: |
      app.zip
    output-dir: ./downloads
```

---

## Distribute with CI

Make your generic artifact versions available for your customers to download.

```yaml
- uses: jfrog/fly-action/distribute@v1       # Distribute publicly
  with:
    name: my-app
    version: '1.0.0'
    type: generic
```

To distribute multiple artifacts, add a separate step for each one. See [Distribution →](../../fly-platform/distribution/) for full details on download URLs, managing distributions, and tracking downloads.

---

## Publish Go modules with CI

Publish your Go modules to Fly Registry so your team can depend on them privately. Add the `go-publish` sub-action to your workflow and every tagged release is published automatically.

```yaml
- uses: jfrog/fly-action/go-publish@v1   # Publish Go module
```

Version is auto-detected from git tags, or you can set it explicitly. See [Go →](../../package-managers/go/) for full details.

---

## Full examples

### npm package workflow

```yaml
name: Build and Publish npm Package

on:
  push:
    branches: [main]

permissions:                                   # Required for Fly OIDC authentication
  contents: read
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
      - uses: jfrog/fly-action@v1              # Setup Fly package managers
      - run: npm install                       # Dependencies from Fly Registry
      - run: npm run build
      - run: npm publish                       # Publish to Fly Registry
```

### Docker image workflow

```yaml
name: Build and Push Docker Image

on:
  push:
    branches: [main]

permissions:                                   # Required for Fly OIDC authentication
  contents: read
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: jfrog/fly-action@v1              # Setup Fly package managers
      - run: docker build -t ${{ env.FLY_REGISTRY_SUBDOMAIN }}/docker/my-app:${{ github.sha }} .
        # Base images pulled from Fly Registry
      - run: docker push ${{ env.FLY_REGISTRY_SUBDOMAIN }}/docker/my-app:${{ github.sha }}
        # Push to Fly Registry
```

### Go module workflow

```yaml
name: Publish Go Module

on:
  push:
    tags: ['v*']

permissions:                                   # Required for Fly OIDC authentication
  contents: read
  id-token: write

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-tags: true                     # Fetch tags for version detection
      - uses: actions/setup-go@v6
        with:
          go-version: '1.26'
      - uses: jfrog/fly-action@v1              # Setup Fly package managers
      - uses: jfrog/fly-action/go-publish@v1   # Publish Go module
```

### Generic artifacts workflow

```yaml
name: Build and Upload Release Artifacts

on:
  push:
    branches: [main]

permissions:                                   # Required for Fly OIDC authentication
  contents: read
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: jfrog/fly-action@v1              # Setup Fly package managers
      - run: make build                        # Build your project
      - uses: jfrog/fly-action/upload@v1       # Upload artifacts to Fly
        with:
          name: my-app
          version: '1.0.0'
          files: |
            dist/app.zip
            dist/app.tar.gz
```

---

## Next steps

- [Coding Agent →](../coding-agent/) - The interface most teams use to configure CI
- [Package Managers →](../../package-managers/) - Per-tool reference and details
- [Releases →](../../fly-platform/releases/) - The release model and lifecycle
- [Where to Use Fly →](../) - The other interfaces
