> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloudeval.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub repository sync

> Connect a GitHub repository to an Infrastructure as code project with the CloudEval GitHub App.

GitHub repository sync keeps GitHub as the source of truth for an Infrastructure as code project. CloudEval imports the selected branch and source root, reads `.cloudeval/config.yaml` when present, resolves linked templates, and refreshes diagrams and reports.

This is the public GitHub App flow for users and organizations. Do not paste app ids, private keys, webhook secrets, or internal callback URLs into repositories; CloudEval manages those server-side.

<Info>
  Want the data-flow and storage boundary before connecting a private repo? Read [Data and model boundaries](/reference/data-and-model-boundaries) for the GitHub import path, source snapshot storage, AI context boundary, and planned Team/Enterprise controls.
</Info>

## Why it matters

Use this path when your source has multiple files, linked ARM templates, or a repository layout you want to keep in GitHub. Source files are read-only in CloudEval while the project is linked to GitHub.

<Tip>
  Want to see CloudEval before connecting Azure or uploading your own source? Start with the [public Azure ARM review example](#public-example-repository), then inspect the passing and failing demo PRs.
</Tip>

## Quick start

<Steps>
  <Step title="Start a GitHub-backed IaC project">
    Open **Projects**, select **New** or **Quick**, choose **Infrastructure as code**, then choose **GitHub repository** as the source.

    Use this source type when GitHub should remain the source of truth. CloudEval imports the selected branch and keeps source files read-only in the CloudEval workspace.
  </Step>

  <Step title="Install or update the CloudEval GitHub App">
    Install the [CloudEval GitHub App](https://github.com/apps/cloudeval-ai) if prompted. Choose the GitHub account or organization, then grant access to the repository or repository set CloudEval should import.

    Organization installs may require a GitHub organization owner or app manager. If the app is already installed, update the installation so the target repository is included.
  </Step>

  <Step title="Choose repository settings">
    Pick the GitHub account or organization, repository, branch, and optional source root.

    Leave source root blank when `.cloudeval/config.yaml`, `azuredeploy.json`, and related templates live at the repository root. Use a source root such as `infra` when the IaC workspace lives in a subdirectory.
  </Step>

  <Step title="Create the project and wait for import">
    Create the project. CloudEval imports files, reads `.cloudeval/config.yaml` when present, resolves linked templates, and starts diagram/report generation in the background.

    The first import should leave the project with repository provenance: repository name, branch, commit SHA, and source root when one was selected.
  </Step>

  <Step title="Verify the sync contract">
    Edit source files in GitHub, then let the push webhook refresh the linked CloudEval project. Use **Sync from GitHub** for a manual refresh.

    If the source file cannot be edited inside CloudEval, that is expected for GitHub-linked projects. The repository remains the editable source of truth.
  </Step>
</Steps>

| Check            | Good state                                                                                                          |
| ---------------- | ------------------------------------------------------------------------------------------------------------------- |
| App installation | The CloudEval GitHub App includes the selected repository.                                                          |
| Project source   | The project shows the selected repository, branch, commit SHA, and source root.                                     |
| Config loading   | `.cloudeval/config.yaml` is read when present, including stack entry files and linked-template resolution settings. |
| Source editing   | Source files are read-only in CloudEval and edited in GitHub.                                                       |
| Ongoing sync     | Pushes to the selected branch refresh the project; **Sync from GitHub** runs the same path manually.                |

## Public example repository

[ganakailabs/cloudeval-azure-arm-review-example](https://github.com/ganakailabs/cloudeval-azure-arm-review-example) is the public reference repo for this flow. It demonstrates:

* repository-root `.cloudeval/config.yaml`
* a parent `azuredeploy.json` with linked templates under `nested/`
* GitHub App import from a branch and source root
* the GitHub Action PR review workflow after a CloudEval project exists
* demo PRs for [passing baseline gates](https://github.com/ganakailabs/cloudeval-azure-arm-review-example/pull/6), [risky regression](https://github.com/ganakailabs/cloudeval-azure-arm-review-example/pull/1), [cost regression](https://github.com/ganakailabs/cloudeval-azure-arm-review-example/pull/2), and [security hardening](https://github.com/ganakailabs/cloudeval-azure-arm-review-example/pull/3)

Use it when you want to see CloudEval's review workflow before granting Azure credentials or connecting a private repository. Fork it when you want to test the end-to-end setup with your own CloudEval project and access key.

| Demo path               | What it proves                                                                                                               |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Public repository       | Nested ARM templates, `.cloudeval/config.yaml`, source-root import, and linked-template resolution are visible before setup. |
| Passing baseline PR     | A green check can still show posture, validation, cost, report links, and source provenance for reviewers.                   |
| Failing demo PRs        | Risk, cost, and security regressions can fail the workflow when configured gates are not satisfied.                          |
| GitHub Actions workflow | The same repository can move from GitHub App sync into PR review once a CloudEval project and CI access key exist.           |

## Recommended repository layout

```text theme={null}
.cloudeval/
  config.yaml
azuredeploy.json
azuredeploy.parameters.json
nested/
  network.json
  storage.json
README.md
```

```yaml theme={null}
# .cloudeval/config.yaml
version: 1
stacks:
  - id: primary-architecture
    name: Primary architecture
    entry: azuredeploy.json
    parameters: azuredeploy.parameters.json
resolve:
  linked_templates: true
analysis:
  auto_resolve_on_import: true
  auto_refresh_on_resolve: true
```

The `entry` file is the visualization source. Relative ARM `templateLink` files are resolved from the same workspace root.

## User and project mapping

GitHub does not decide which CloudEval user owns a project. CloudEval maps the GitHub App installation to the signed-in CloudEval user who starts the install flow.

```mermaid theme={null}
sequenceDiagram
    participant User as Signed-in CloudEval user
    participant CE as CloudEval
    participant GH as GitHub App
    participant Job as Sync worker

    User->>CE: Import from GitHub repository
    CE->>GH: Redirect with signed state containing CloudEval user id
    GH->>User: Choose account/org and repository access
    GH->>CE: Callback with installation id and state
    CE->>CE: Link installation id to CloudEval user
    User->>CE: Pick repo, branch, source root
    CE->>Job: Import, resolve, refresh reports
```

If an organization admin installs the app, the project still belongs to the CloudEval user who completed the flow. For team use, share the CloudEval project with teammates after creation.

## What GitHub data CloudEval stores

CloudEval stores provenance on the project:

```json theme={null}
{
  "type": "github",
  "installation_id": 123456,
  "repo_full_name": "org/repo",
  "ref": "main",
  "commit_sha": "abc123",
  "source_root": "infra",
  "display_label": "org/repo main"
}
```

CloudEval does not store long-lived GitHub access tokens. It stores the installation id and mints short-lived installation tokens server-side when it needs to list repositories, fetch files, or process a sync.

CloudEval also stores the imported source snapshot and generated evidence needed for diagrams, reports, exports, and review comments. For the current public Pro plan, that project storage is CloudEval-managed. Team and Enterprise private deployment, customer-managed storage, and custom LLM gateway options are planned controls rather than self-serve Pro behavior today. See [Data and model boundaries](/reference/data-and-model-boundaries).

## Sync behavior

| Action                  | What happens                                                                           |
| ----------------------- | -------------------------------------------------------------------------------------- |
| Project creation        | Imports selected files, resolves `.cloudeval/config.yaml`, starts diagram/report jobs  |
| Push to selected branch | GitHub sends a signed webhook; CloudEval imports the new commit and refreshes analysis |
| **Sync from GitHub**    | Manually runs the same import/resolve/refresh path                                     |
| GitHub App removed      | CloudEval marks the installation unavailable; reconnect GitHub before syncing again    |

Public repositories can be imported through a GitHub URL for a one-time single-template flow. Use the GitHub App flow when you want ongoing sync, commit provenance, branch selection, and push webhooks.

## Files CloudEval imports

CloudEval preserves repository-relative paths under the selected source root. For example, `source_root: infra` maps `infra/azuredeploy.json` to `azuredeploy.json` in the CloudEval workspace.

The GitHub App resolves the selected branch to a commit SHA, reads UTF-8 text files through a short-lived installation token, and imports a bounded snapshot for analysis. Current limits are 1 MB per file, 20 MB total content per sync, and 500 imported files.

CloudEval skips unsafe or noisy paths:

* `.git/**`
* `.github/**`
* `node_modules/**`
* `.terraform/**`
* `*.tfstate` and `*.tfstate.*`
* `.env` and `.env.*`
* CloudEval-generated `.cloudeval/bundles/**`, `.cloudeval/connections/**`, `.cloudeval/template-cache/**`, and `.cloudeval/snapshots/**`

## GitHub App permissions

For V1 repository sync, the GitHub App needs only read-oriented repository access:

| Permission or event | Why                                                      |
| ------------------- | -------------------------------------------------------- |
| Metadata read       | Identify installed repositories and account/org metadata |
| Contents read       | Read source files from the selected branch/source root   |
| Push event          | Refresh linked projects when the selected branch changes |

Pull request permissions are not required for V1 sync. They are only needed for later PR comments, checks, or GitHub Action workflows.

## GitHub Actions and PR review

The CloudEval GitHub Action is optional. It is useful after a project exists when you want CI gates, report runs, or PR comments. It is not required for repository sync.

Use the App and Action together like this:

<Steps>
  <Step title="Create the CloudEval project through the GitHub App">
    Use the **GitHub App** to install repository access and create the CloudEval project.
  </Step>

  <Step title="Create a CI access key">
    Create a **GitHub Actions CI** access key scoped to that project. Include `github:comment` if PR comments should come from the CloudEval GitHub App identity.
  </Step>

  <Step title="Add the action workflow">
    Add the action workflow to the same repository and pass `project_id`.
  </Step>

  <Step title="Require the workflow job">
    Require that workflow job in branch protection if it should block merges.
  </Step>
</Steps>

Use `mode: review` when a pull request should sync the pushed commit to the linked CloudEval project and post a summary:

```yaml theme={null}
permissions:
  contents: read
  pull-requests: write
  issues: write

on:
  pull_request:

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ganakailabs/cloudeval-action@v1
        with:
          access_key: ${{ secrets.CLOUDEVAL_ACCESS_KEY }}
          project_id: ${{ secrets.CLOUDEVAL_PROJECT_ID }}
          mode: review
          post_pr_comment: true
          upload_artifacts: true
```

Review gates come from `.cloudeval/config.yaml` `ci.gates`. Missing gates warn rather than fail. See [IaC project config](/reference/iac-project-config) for the commented config example, gate thresholds, PDF output settings, and PR comment wording.

To attach the generated PDF from each review run, keep `upload_artifacts: true`
and enable `.cloudeval/config.yaml` `ci.review.outputs.pdf.enabled`. The PR
comment keeps the CloudEval-hosted `PDF` badge, and the workflow artifact
contains `review/review.pdf` for that specific run.

When the project is linked through the CloudEval GitHub App and the CI access
key includes `github:comment`, PR review comments are posted by the CloudEval
GitHub App identity. If that app comment path is unavailable, the action falls
back to `github-actions[bot]`.

## Troubleshooting

| Symptom                                      | Fix                                                                                        |
| -------------------------------------------- | ------------------------------------------------------------------------------------------ |
| Repository does not appear                   | Reinstall or update the GitHub App and include that repository in the selected access list |
| Branch list is empty                         | Confirm the GitHub App still has contents read access to the repo                          |
| Sync says GitHub is disconnected             | The app was removed or suspended; reconnect from the GitHub repository source picker       |
| Diagram/report does not include linked files | Add or fix `.cloudeval/config.yaml` and set `stacks[].entry` to the parent template        |
| Source file cannot be edited                 | This is expected for GitHub-linked projects. Edit in GitHub, then sync again               |

## Related pages

* [IaC project config](/reference/iac-project-config)
* [Data and model boundaries](/reference/data-and-model-boundaries)
* [Import an ARM or Bicep template](/quickstart/import-an-arm-or-bicep-template)
* [GitHub Actions integration](/workflows/github-actions)
