Documentation
¶
Overview ¶
Package ship — hook.go provides the pre-push hook content and installation.
Package ship implements the deterministic agent pipeline guardrail. It wraps pre-flight checks, git push, PR creation, and synchronous CI polling into a single blocking operation so AI agents cannot skip post-merge verification.
Index ¶
- Constants
- Variables
- func CreatePR(dir, commitMsg, baseBranch string) (string, error)
- func CurrentBranch(dir string) string
- func DetectAllStacks(dir string) []*stackInfo
- func DetectStack(dir string) *stackInfo
- func GitPush(dir, commitMsg, branch string) error
- func HasStagedChanges(dir string) bool
- func HasUnpushedCommits(dir, baseRef string) bool
- func InstallPreCommitHook(repoDir string) error
- func InstallPrePushHook(repoDir string) error
- func IsPreCommitHookInstalled(repoDir string) bool
- func IsPrePushHookInstalled(repoDir string) bool
- func LatestCommitMessage(dir string) (string, error)
- func MergePR(dir, prURL string) error
- func SplitCommitMessage(msg string) (title, body string)
- func WatchPRChecks(dir, prURL, branch string, timeout time.Duration) (runID, conclusion string, failureLogs []string, err error)
- type Options
- type PipelineConfig
- type PipelineStage
- type PreFlightResult
- type Result
Constants ¶
const ( ExitOK = 0 ExitPreFlightFail = 50 ExitPushFail = 51 ExitPRFail = 52 ExitCIFail = 53 ExitCITimeout = 54 ExitDocCheckFail = 55 ExitNothingToShip = 56 )
ExitCodes for deterministic agent error handling.
const PreCommitHookContent = `` /* 2167-byte string literal not displayed */
PreCommitHookContent is the shell script installed into .git/hooks/pre-commit. It prevents direct commits to protected trunk branches and forces developers to work on feature branches. Humans can bypass with: git commit --no-verify
const PrePushHookContent = `` /* 2577-byte string literal not displayed */
PrePushHookContent is the shell script installed into .git/hooks/pre-push. It runs devx audit (secrets + vulnerability scanning) first, then blocks all git push attempts and directs agents to use devx agent ship. Humans can bypass with: git push --no-verify
Variables ¶
var ErrNoStack = errors.New("no recognized stack detected (go.mod, package.json, Cargo.toml, pyproject.toml, pom.xml, build.gradle, *.csproj) and no pipeline: block in devx.yaml — pre-flight checks were skipped")
ErrNoStack is returned when no stack is detected and no explicit pipeline exists. Callers should surface this as a warning to the developer.
Functions ¶
func CreatePR ¶ added in v0.34.0
CreatePR creates a GitHub PR from a commit-message-style string. The first line of commitMsg becomes the PR title; the remainder (if any) becomes the PR body. Splitting is required because GitHub's API rejects titles that contain newlines or exceed ~256 chars, so passing the full multi-line `-m` payload as the title returns a 422 and surfaces as `gh pr create: exit 1`. Returns the PR URL.
func CurrentBranch ¶
CurrentBranch returns the current git branch name.
func DetectAllStacks ¶ added in v0.44.0
func DetectAllStacks(dir string) []*stackInfo
DetectAllStacks returns all matching stacks for the given directory. This enables multi-stack monorepo support.
func DetectStack ¶
func DetectStack(dir string) *stackInfo
DetectStack profiles the repository by looking for marker files. Returns the first matching stack (highest precedence).
func GitPush ¶
GitPush commits any working-tree changes (no-op if already committed) and pushes to a feature branch using --no-verify to bypass our own pre-push hook.
func HasStagedChanges ¶
HasStagedChanges checks if there are any uncommitted changes.
func HasUnpushedCommits ¶ added in v0.58.0
HasUnpushedCommits reports whether the current branch has commits that are not present on baseRef (e.g. "origin/main"). This lets review/ship recognize already-committed work that still needs pushing even when the working tree is clean. Returns false if the comparison can't be made (e.g. baseRef missing).
func InstallPreCommitHook ¶ added in v0.45.0
InstallPreCommitHook writes the pre-commit hook into .git/hooks/. If any devx-managed hook already exists, it will be safely overwritten. If a non-devx hook exists, it returns an error to avoid clobbering.
func InstallPrePushHook ¶
InstallPrePushHook writes the pre-push hook into .git/hooks/. If any devx-managed hook already exists, it will be safely overwritten. If a non-devx hook exists, it returns an error to avoid clobbering.
func IsPreCommitHookInstalled ¶ added in v0.45.0
IsPreCommitHookInstalled checks if a devx pre-commit hook is present.
func IsPrePushHookInstalled ¶
IsPrePushHookInstalled checks if a devx pre-push hook is present.
func LatestCommitMessage ¶ added in v0.58.0
LatestCommitMessage returns the full message (subject + body) of HEAD's most recent commit, trimmed. Used to derive a PR title/body for an already-committed branch where there's no working-tree diff to summarize.
func MergePR ¶ added in v0.34.0
MergePR merges the given PR using admin privileges. Captures stderr so transient failures (mergeability race, branch-protection edge cases) surface a real error message instead of an opaque exit code.
func SplitCommitMessage ¶ added in v0.45.0
SplitCommitMessage splits a commit-style string into (title, body) using the first newline as the separator. Surrounding whitespace is trimmed from both halves. The body preserves its internal blank lines.
func WatchPRChecks ¶ added in v0.34.0
func WatchPRChecks(dir, prURL, branch string, timeout time.Duration) (runID, conclusion string, failureLogs []string, err error)
WatchPRChecks waits for the PR checks to complete using gh pr checks --watch. It blocks until the pipeline finishes or the timeout expires. Returns the run conclusion and any failure logs.
Types ¶
type Options ¶
type Options struct {
CommitMsg string
Branch string // target branch (default: current)
BaseBranch string // base branch for PR (default: main)
Verbose bool
JSON bool
NonInteractive bool
SkipPreFlight bool
CITimeout time.Duration
}
Options configures a ship run.
type PipelineConfig ¶ added in v0.30.0
type PipelineConfig struct {
Test *PipelineStage
Lint *PipelineStage
Build *PipelineStage
Verify *PipelineStage
}
PipelineConfig holds explicit pipeline stage overrides from devx.yaml. When non-nil, auto-detection via DetectStack is bypassed entirely ("Explicit Wins").
type PipelineStage ¶ added in v0.30.0
type PipelineStage struct {
Cmds [][]string // Resolved commands to run sequentially
Before [][]string // Pre-stage hooks (run before Cmds)
After [][]string // Post-stage hooks (run after Cmds)
}
PipelineStage defines a single pipeline step with support for multi-command and lifecycle hooks (before/after).
type PreFlightResult ¶
type PreFlightResult struct {
Stack string `json:"stack"`
TestPass bool `json:"test_pass"`
LintPass bool `json:"lint_pass"`
BuildPass bool `json:"build_pass"`
TestSkipped bool `json:"test_skipped,omitempty"`
LintSkipped bool `json:"lint_skipped,omitempty"`
BuildSkipped bool `json:"build_skipped,omitempty"`
}
PreFlightResult holds the outcome of each local pre-flight step.
func RunPreFlight ¶
func RunPreFlight(dir string, verbose bool, pipeline *PipelineConfig) (*PreFlightResult, error)
RunPreFlight executes local tests, linter, and build. If an explicit pipeline is provided, it takes precedence over auto-detection.
type Result ¶
type Result struct {
Success bool `json:"success"`
ExitCode int `json:"exit_code"`
Phase string `json:"phase"`
Message string `json:"message"`
PRURL string `json:"pr_url,omitempty"`
CIRunID string `json:"ci_run_id,omitempty"`
CIStatus string `json:"ci_status,omitempty"`
FailureLogs []string `json:"failure_logs,omitempty"`
PreFlight *PreFlightResult `json:"pre_flight,omitempty"`
}
Result is the machine-readable output of a ship operation.