mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-09-01 05:07:59 +00:00
48f010475b
* feat(gitops): resolve branch, tag, and SHA refs to immutable commits before fetch The ref model now resolves a configured branch, tag, or full commit SHA to an immutable commit before any content is downloaded, and records both the configured and the resolved identity where revision state persists. - RefKind (branch | tag | sha) is a resolved property, not caller-asserted. A bare string resolves branch-first, then tag; a full 40/64-hex SHA self-resolves with no remote round-trip. Branch and tag both fetch via a bare --branch name; a SHA uses init + shallow fetch + detached checkout. - A single ls-remote with narrow heads/tags refspecs pins the configured ref to an immutable SHA; rev-parse HEAD must equal the resolved SHA or the fetch refuses (tip-changed) instead of materializing unreviewed content. - Error union grew: REF_NOT_FOUND (ref-neutral, replaces BRANCH_NOT_FOUND), UNSUPPORTED_REF (a pinned SHA the host will not serve), and a service-level REF_DELETED upgrade that fires when a classified REF_NOT_FOUND occurs for a source with prior fetch history (a vanished ref reads as delete/force-push, not a fresh typo). Status mapping: REF_NOT_FOUND/REF_DELETED to 404, UNSUPPORTED_REF to 400. - Configured-vs-resolved identity is recorded via a nullable resolved_ref_kind column on gitops_generations (added to CREATE TABLE and re-added for legacy installs through maybeAddCol). The kind is deliberately NOT in the plan fingerprint: two sources naming the same commit differently are the same plan. Docs updated (git-sources feature page, connect-a-git-source tutorial, and the native-git-transport internal deep-dive) to the ref-neutral naming. * fix(gitops): harden ref resolution after pre-merge audit Request peeled annotated-tag refs from ls-remote, detect force-pushes and ref-kind changes against prior fetch identity, persist resolved kind on application rows, and add real-git tag/SHA integration coverage plus ref-neutral UI and operator docs. * test(gitops): mock verifyFastForward in direct producer suite The producer tests stub the transport seam but were missing resolved kind on resolveRef and a verifyFastForward stub, so second pulls tripped the new ref-continuity checks as REF_DELETED. * test(git): remove unused buildBareFixtureRepo helper Fixes backend lint failure after the integration fixture was refactored to buildRichFixtureRepo without dropping the old wrapper. * fix(gitops): correct fast-forward ancestry verification under size bounds Replace the dual shallow-fetch ancestry probe with a single-tip deepen strategy, keep verifier Git work inside the transport watchdog, and add real-Git regression coverage for linear advances and rewritten history. * fix(gitops): bound fast-forward verification with exponential deepen Replace per-commit deepen loops with exponential steps, cap remote fetch rounds, and share one deadline across verifier Git calls. Budget exhaustion now surfaces as a classified timeout instead of REF_DELETED. * fix(gitops): classify fast-forward probe failures accurately Normalize verifier probe timeouts and unexpected exit codes into transport failures, interpret merge-base status 1 as proven non-ancestry only, and treat shallow stagnation as timeout instead of REF_DELETED. * fix(gitops): satisfy tsc on probeFailure never returns * fix(gitops): address Phase E QA findings on ref verification Remove the fast-forward scratch repo after verification so pull size caps are not inflated, classify GitHub not-our-ref as UNSUPPORTED_REF, persist fetched_resolved_ref_kind on create-from-git, and broaden REF_DELETED copy for retagged tags.
100 lines
7.8 KiB
Plaintext
100 lines
7.8 KiB
Plaintext
---
|
|
title: Deploy Compose Changes by Pulling From Git Instead of Editing by Hand
|
|
sidebarTitle: Deploy compose changes from Git
|
|
description: Link a running stack to a Git repository, pull a real commit, review the classified change plan, and deploy it, instead of hand-editing the compose file in the browser.
|
|
---
|
|
|
|
Say `marketing-site` is a small nginx stack you created directly in Sencho, and your team has decided the compose file should live in a Git repository instead, so changes go through a commit and a pull request before they reach the stack. This walks through connecting that already-running stack to a repository, pulling a real commit a teammate pushed, reviewing the classified change plan Sencho builds against what is on disk, and applying it, which both writes the new files and redeploys the container.
|
|
|
|
This tutorial covers linking an existing stack to a Git source and running one manual pull-review-apply cycle. It doesn't cover creating a brand-new stack directly from a repository, the three webhook-driven apply modes, or multi-file compose sources; see the [Git Sources](/features/git-sources) feature page for all of that.
|
|
|
|
## Prerequisites
|
|
|
|
- The `admin` or `node-admin` role. Linking a source and running a pull or apply needs the `stack:edit` permission, which `deployer`, `viewer`, and `auditor` do not hold.
|
|
- A running stack to link. If you don't have one, select **Create Stack**, name it `marketing-site`, and replace its compose file with:
|
|
|
|
```yaml
|
|
services:
|
|
web:
|
|
image: nginx:1.27-alpine
|
|
restart: always
|
|
ports:
|
|
- "8098:80"
|
|
```
|
|
|
|
Select **Save & Deploy**. This tutorial's steps and screenshots use this exact stack, so if you use a different name or port, adjust accordingly.
|
|
- A public Git repository over HTTPS that you control, with a compose file committed at its root. The screenshots below use a small throwaway demo repository; any repository with the same shape works.
|
|
- Available on every tier, including Community; no Admiral requirement.
|
|
|
|
<Steps>
|
|
<Step title="Open the Git Source panel">
|
|
Open the `marketing-site` stack and select **Git Source** in the editor toolbar. The panel opens empty, since nothing is linked yet.
|
|
|
|
<Frame>
|
|
<img src="/images/tutorials/connect-a-git-source/git-source-panel-empty.png" alt="Empty Git source panel for the marketing-site stack, showing blank Repository URL and Ref fields defaulted to main, a compose.yaml entry marked primary in Compose files, Public (no auth) selected under Authentication, and Review only selected under Apply behavior." />
|
|
</Frame>
|
|
</Step>
|
|
<Step title="Point it at your repository">
|
|
Paste your repository's HTTPS URL into **Repository URL** (for example `https://github.com/your-org/your-repo.git`). Leave **Ref** on its default, `main`, unless your repository uses a different branch, tag, or pinned commit SHA.
|
|
|
|
Select **Browse** to confirm Sencho can actually reach the repository and see its files, rather than trusting the URL is correct. The browser lists every file in the repository; `compose.yaml` is already ticked as the primary compose file, since that name matches the picker's default.
|
|
|
|
<Frame>
|
|
<img src="/images/tutorials/connect-a-git-source/browse-picker.png" alt="Git source panel with a Repository URL filled in and the Browse file picker open below the Compose files list, showing a checked compose.yaml and an unchecked README.md fetched live from the repository." />
|
|
</Frame>
|
|
|
|
Leave **Authentication** on **Public (no auth)** for a public repository, and **Apply behavior** on **Review only**, the safest default: a pull only stages a change plan for you to review, it never writes or deploys on its own. Select **Save**. Sencho runs a reachability check against the repository before persisting anything; if that check fails, nothing is saved and the panel reports why.
|
|
</Step>
|
|
<Step title="Pull the latest commit">
|
|
Now make a change the way your team actually would: edit the compose file in your repository (not in Sencho) and push a commit. For this tutorial, bump the pinned tag from `nginx:1.27-alpine` to `nginx:1.28-alpine` and push it to the ref you configured.
|
|
|
|
Back in the Git Source panel, select **Pull now**. Sencho fetches the ref's current commit and opens a classified change plan against what's on disk.
|
|
|
|
<Frame>
|
|
<img src="/images/tutorials/connect-a-git-source/pull-preview-diff.png" alt="GIT · CHANGE PLAN dialog for marketing-site, listing a Modify row for compose.yaml (image tag change) with Deploy after apply and Apply in the footer." />
|
|
</Frame>
|
|
|
|
The plan lists only the files that actually change. If the incoming compose file failed `docker compose config` validation, an error banner would appear here and the **Apply** button would stay disabled; since this pull is clean, Apply is enabled.
|
|
</Step>
|
|
<Step title="Apply and deploy in one step">
|
|
Tick **Deploy after apply** at the bottom of the dialog, then select **Apply**. This both writes the incoming file to disk and runs `docker compose up -d` against it, so the running container picks up the new tag immediately instead of just staging the file for a later manual deploy.
|
|
|
|
Sencho shows the deploy's progress the same way any other deploy does, ending in a health check on the recreated container.
|
|
</Step>
|
|
</Steps>
|
|
|
|
## Verify it worked
|
|
|
|
Check from two places, since neither alone proves the pull was actually applied and deployed.
|
|
|
|
**The Git Source panel.** Reopen it. The stat strip at the bottom now shows the short SHA of the commit you just pulled, with an updated timestamp, and a **Source state** of `accepted`, meaning Sencho took that commit as the current generation rather than merely writing its files. Nothing is listed at the top of the panel, which is what a stack with complete evidence looks like.
|
|
|
|
<Frame>
|
|
<img src="/images/tutorials/connect-a-git-source/last-applied-commit.png" alt="Git source panel for marketing-site with Apply behavior still on Review only, and a stat strip at the bottom showing a short commit SHA, a Source state of accepted, and a just-now timestamp." />
|
|
</Frame>
|
|
|
|
**The stack itself.** Reopen `marketing-site`. The container recreated on the new image: a fresh uptime, and its logs now start with `nginx/1.28.3` instead of `1.27.5`. The compose editor tab reflects the same change; if it still shows the old tag, reload the page, since the editor buffer doesn't refresh itself after a Git-driven write.
|
|
|
|
<Frame>
|
|
<img src="/images/tutorials/connect-a-git-source/stack-redeployed.png" alt="marketing-site stack page after redeploy, showing marketing-site-web-1 up about a minute, logs starting from nginx/1.28.3, and the compose editor showing image nginx:1.28-alpine." />
|
|
</Frame>
|
|
|
|
## If something goes wrong
|
|
|
|
**Saving the source fails with "The configured branch, tag, or commit was not found," even though the URL is right.** Ref names are case-sensitive, and a typo there (`Main` instead of `main`, for example) surfaces as a distinct not-found error rather than a repository error, because Sencho resolves the ref on the remote before fetching. Double-check the ref against what your Git host actually shows before assuming the URL itself is wrong.
|
|
|
|
<Frame>
|
|
<img src="/images/tutorials/connect-a-git-source/branch-error.png" alt="Git source panel with Ref set to the incorrect value Main, and a red error toast in the corner reading The configured branch, tag, or commit was not found." />
|
|
</Frame>
|
|
|
|
## Related
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Git Sources" icon="code-branch" href="/features/git-sources">
|
|
Multi-file sources, the three webhook apply modes, private-repo authentication, and the full troubleshooting table.
|
|
</Card>
|
|
<Card title="Deploy a Stack Automatically From Your CI Pipeline" icon="satellite-dish" href="/tutorials/set-up-a-webhook">
|
|
Trigger a Git source pull and deploy from CI instead of pulling by hand from the panel.
|
|
</Card>
|
|
</CardGroup>
|