Documentation
¶
Index ¶
- Constants
- func CheckModuleMajor(workDir, version string) error
- func CleanupPreparedNotes(workDir, version string) error
- func CleanupPreparedTagVersion(workDir string) error
- func CleanupPreparedVersion(workDir string) error
- func CleanupTagMessage(workDir string) error
- func DisplayWorkflowStatus(w *remote.Workflow)
- func GetReleaseNotesFile(version string) string
- func HasPreparedNotes(workDir, version string) bool
- func HasPreparedTagVersion(workDir string) bool
- func HasPreparedVersion(workDir string) bool
- func HasTagMessage(workDir string) bool
- func JudgeMergeTarget(localSHA, prHeadSHA string) (proceed bool, message string)
- func JudgeWatchTarget(localSHA, prHeadSHA string) (proceed bool, message string)
- func LoadPreparedNotes(workDir, version string) (string, error)
- func LoadPreparedTagVersion(workDir string) (string, error)
- func LoadPreparedVersion(workDir string) (string, error)
- func LoadTagMessage(workDir string) (string, error)
- func NextVersion(current string, counts CommitCounts) string
- func ParseWorkflowInputs(pairs []string) (map[string]string, error)
- func SavePreparedTagVersion(workDir, version string) error
- func SavePreparedVersion(workDir, version string) error
- func SaveTagMessage(workDir, message string) error
- func SuggestTagVersion(workDir string) string
- type ArtifactCleanupAction
- type ArtifactDownloadAction
- type ArtifactListAction
- type ArtifactProvider
- type ArtifactStatsAction
- type CPWPlan
- type CommitCounts
- type CommitInfo
- type CommitPushWatchAction
- type PRAction
- type PREditAction
- type PRInfo
- type ReleaseAction
- type ReleaseCommitAction
- type ReleasePrepareAction
- type ReleasePreviewAction
- type TagCreateAction
- type TagDeleteAction
- type TagListAction
- type TagPrepareAction
- type TagPreviewAction
- type VersionState
- type WorkflowListAction
- type WorkflowRerunAction
- type WorkflowRunAction
- type WorkflowWatchAction
Constants ¶
const CommitLogFormat = "--pretty=format:%H|%s|%b<<<END>>>"
CommitLogFormat is the git log format ParseCommitLog reads.
const ReleaseNotesFilePattern = ".cidx/release-notes-v%s.md"
ReleaseNotesFilePattern is the pattern for release notes files
const ReleaseVersionFile = ".cidx/release-version"
ReleaseVersionFile is the path where the target version is stored
const TagMessageFile = ".cidx/tag-message"
TagMessageFile is the path where the tag message is stored
const TagVersionFile = ".cidx/tag-version"
TagVersionFile is the path where the target tag version is stored
Variables ¶
This section is empty.
Functions ¶
func CheckModuleMajor ¶
CheckModuleMajor reports whether go.mod may be tagged as version.
Go resolves a module by its declared path, so `module .../cidx/v2` tagged v3.0.0 is not v3 of anything: `go list -m .../cidx/v3` answers "go.mod has non-.../v3 module path", and `go install .../cidx/v2/cmd/cidx@latest` — the line `cidx generate github` writes into every bootstrapped workflow — quietly resolves to the newest v2 instead. The v3.0.0 release shipped exactly that (issue #395), and it was the second time: #187 was the same mismatch one major earlier, fixed by editing the path once, with nothing left to catch the next one.
So the check is here rather than in a checklist. It runs where a major becomes permanent — the tag — and it is one comparison.
Only a major bump is constrained. v3.0.1 on a /v3 module is fine, and so is any v0/v1 tag on an unsuffixed path, which is the convention Go itself defines rather than an omission.
func CleanupPreparedNotes ¶
CleanupPreparedNotes removes the release notes file after successful release
func CleanupPreparedTagVersion ¶
CleanupPreparedTagVersion removes the version file after successful tag creation
func CleanupPreparedVersion ¶
CleanupPreparedVersion removes the version file after successful release
func CleanupTagMessage ¶
CleanupTagMessage removes the message file after successful tag creation
func DisplayWorkflowStatus ¶
DisplayWorkflowStatus renders the current workflow status to stdout Used by release, commit-push-watch, and other actions that watch workflows
func GetReleaseNotesFile ¶
GetReleaseNotesFile returns the path for release notes with the given version
func HasPreparedNotes ¶
HasPreparedNotes checks if release notes have been prepared for the given version
func HasPreparedTagVersion ¶
HasPreparedTagVersion checks if a tag version has been prepared
func HasPreparedVersion ¶
HasPreparedVersion checks if a version has been prepared
func HasTagMessage ¶
HasTagMessage checks if a tag message has been prepared
func JudgeMergeTarget ¶ added in v3.2.0
JudgeMergeTarget decides whether a merge may land, given the same two commits.
Both directions refuse, and they are different accidents. Ahead — commits that never reached the remote — is the destructive one: they are merged around, then deleted with the branch. Behind destroys nothing but merges code the reader has not seen. Telling them apart needs the remote commit to exist locally, which is exactly what is not guaranteed here, so the refusal names both remedies rather than guessing.
func JudgeWatchTarget ¶ added in v3.2.0
JudgeWatchTarget decides whether a watch may report, given the commit in hand and the commit the provider holds checks for.
Either SHA may be empty, meaning it could not be established. That does not refuse: the guard exists to stop a confident wrong answer, and "I could not tell" is not one — a watch is still the useful thing to run. What it must not do is stay quiet, because an unverified report would then be indistinguishable from a verified one.
func LoadPreparedNotes ¶
LoadPreparedNotes loads previously prepared release notes for the given version
func LoadPreparedTagVersion ¶
LoadPreparedTagVersion loads the target version from file
func LoadPreparedVersion ¶
LoadPreparedVersion loads the target version from file
func LoadTagMessage ¶
LoadTagMessage loads the tag message from file
func NextVersion ¶
func NextVersion(current string, counts CommitCounts) string
NextVersion applies the semantic bump implied by counts to current.
func ParseWorkflowInputs ¶
ParseWorkflowInputs turns repeated `key=value` flags into the input map the provider takes. Values are passed through unchanged, including empty ones; only a malformed pair or a repeated key is rejected, because both mean the user asked for something other than what would be sent.
func SavePreparedTagVersion ¶
SavePreparedTagVersion saves the target version to a file
func SavePreparedVersion ¶
SavePreparedVersion saves the target version to a file
func SaveTagMessage ¶
SaveTagMessage saves the tag message to a file
func SuggestTagVersion ¶
SuggestTagVersion returns the version the tag flow should create: the pending one when a bump already landed untagged, otherwise the semantic bump of the latest tag.
Types ¶
type ArtifactCleanupAction ¶
type ArtifactCleanupAction struct {
// contains filtered or unexported fields
}
ArtifactCleanupAction deletes artifacts
func NewArtifactCleanup ¶
func NewArtifactCleanup(provider remote.Provider, deleteAll, expired bool, olderThan int, dryRun bool) *ArtifactCleanupAction
NewArtifactCleanup creates a new artifact cleanup action
type ArtifactDownloadAction ¶
type ArtifactDownloadAction struct {
// contains filtered or unexported fields
}
ArtifactDownloadAction fetches the artifacts of one run onto disk.
It exists because `cidx security vuln prune --results DIR` and `cidx security baseline --results DIR` read files that only a workflow run produces, and until now the only way to put them there was `gh run download` -- a cidx command depending on artifacts with no cidx command able to obtain them (issue #285).
Three things it does that the shell-out did not, each one a bug paid for:
- It reads the repository from the git remote of the working directory, the way every other cidx command does. `gh run download <id>` run outside a checkout resolves the id against whatever repository gh last knew about and answers with another repository's artifacts, silently; that skewed a before/after measurement in #327.
- It writes one flat directory. `gh run download` unpacks a subdirectory per artifact, and the readers of these files join `dir` with a file name -- twelve `trivy-N/` subdirectories are twelve directories none of them looks in (#333).
- It never fails on a name two artifacts share. Identical content is skipped; differing content keeps the first copy and says which artifacts disagreed, because that is a fact about the run worth hearing, not a reason to abandon a download halfway through.
func NewArtifactDownload ¶
func NewArtifactDownload(provider remote.Provider, runID string, patterns []string, dir string) *ArtifactDownloadAction
NewArtifactDownload creates an artifact download action. patterns are glob patterns matched against artifact names; an empty list takes every artifact of the run.
type ArtifactListAction ¶
type ArtifactListAction struct {
// contains filtered or unexported fields
}
ArtifactListAction lists all artifacts
func NewArtifactList ¶
func NewArtifactList(provider remote.Provider, verbose bool) *ArtifactListAction
NewArtifactList creates a new artifact list action
type ArtifactProvider ¶
type ArtifactProvider interface {
ListArtifacts(ctx context.Context) (*remote.ArtifactStats, error)
DeleteArtifact(ctx context.Context, artifactID int64) error
DeleteArtifactsBefore(ctx context.Context, before time.Time) (deleted int, freedBytes int64, err error)
DeleteAllArtifacts(ctx context.Context) (deleted int, freedBytes int64, err error)
DeleteExpiredArtifacts(ctx context.Context) (deleted int, freedBytes int64, err error)
}
ArtifactProvider is the interface for artifact operations Only GitHub supports artifacts currently
type ArtifactStatsAction ¶
type ArtifactStatsAction struct {
// contains filtered or unexported fields
}
ArtifactStatsAction shows artifact storage statistics
func NewArtifactStats ¶
func NewArtifactStats(provider remote.Provider) *ArtifactStatsAction
NewArtifactStats creates a new artifact stats action
type CPWPlan ¶ added in v3.2.0
type CPWPlan int
CPWPlan is what a cpw run has to do, decided before it does any of it.
func PlanCommitPushWatch ¶ added in v3.2.0
PlanCommitPushWatch decides what a cpw run does.
The bug this exists to prevent is one step: cpw asked whether there was anything to commit and returned when there was not, before ever reaching its push. A branch whose commits were already written and whose tree was clean therefore never left the machine, while the message — "No changes to commit" — was true and read like "nothing to do".
Everything downstream then behaved correctly about the wrong commit: the provider reported checks for the commit before, and a watch called them green. #414 and #415 refuse those answers; this is why they rarely have to.
func (CPWPlan) RunsCodePhase ¶ added in v3.2.0
RunsCodePhase reports whether a plan puts something new in front of CI.
A push of commits written by hand earns the same gate as a push of one cpw just made (#307): the phase is about what CI is going to run, not about how the commit came to exist.
type CommitCounts ¶
CommitCounts is the conventional-commit breakdown of a commit range.
func CountCommitInfos ¶
func CountCommitInfos(commits []CommitInfo) CommitCounts
CountCommitInfos is countCommits for callers that already parsed the range.
func (CommitCounts) Total ¶
func (c CommitCounts) Total() int
Total returns the number of commits in the range.
type CommitInfo ¶
type CommitInfo struct {
Hash string
Type string
Scope string
Subject string
Body string
PR int
Breaking bool
}
CommitInfo holds parsed commit information
func ParseCommit ¶
func ParseCommit(subject, body string) CommitInfo
ParseCommit is the single conventional-commit parser of the release flow: prepare, preview, tag and the TUI all classify commits through it, so they cannot disagree on a version bump. Subjects that are not conventional keep type "other" and their raw text.
func ParseCommitLog ¶
func ParseCommitLog(output string) []CommitInfo
ParseCommitLog parses `git log CommitLogFormat` output into commits.
type CommitPushWatchAction ¶
type CommitPushWatchAction struct {
// contains filtered or unexported fields
}
CommitPushWatchAction orchestrates commit, push, and CI watching
func NewCommitPushWatch ¶
func NewCommitPushWatch(repo *vcs.Repository, provider remote.Provider, message string, verify bool) *CommitPushWatchAction
NewCommitPushWatch creates a new commit-push-watch action
type PRAction ¶
type PRAction struct {
// contains filtered or unexported fields
}
PRAction manages pull request workflow
func NewPR ¶
func NewPR(repo *vcs.Repository, resolveProvider remote.ProviderFunc, title, issueNum string, dryRun, readyMode bool) *PRAction
NewPR creates a new PR action. The provider is passed as a resolver, not a value: `pr create --dry-run` and `pr ready --dry-run` describe the work from local state alone, and building a provider up front made them fail on an unparseable remote URL -- or a missing token -- before printing a line (issue #350). Same shape #227 gave the release commands.
func NewPRMerge ¶
func NewPRMerge(repo *vcs.Repository, provider remote.Provider, mergeMethod string, watchFlow, skipChecks, dryRun bool) *PRAction
NewPRMerge creates a new PR merge action. It takes a provider outright: every path through the merge, dry run included, resolves the pull request it would merge, so there is nothing to defer.
type PREditAction ¶
type PREditAction struct {
// contains filtered or unexported fields
}
PREditAction updates the title and/or body of the current branch's PR.
func NewPREdit ¶
func NewPREdit(repo *vcs.Repository, provider remote.Provider, title, body string) *PREditAction
NewPREdit creates a new PR edit action. Empty title/body fields are left unchanged on the PR; at least one must be provided.
type ReleaseAction ¶
type ReleaseAction struct {
// contains filtered or unexported fields
}
ReleaseAction orchestrates the release process using dynamic action configuration
func NewRelease ¶
func NewRelease(repo *vcs.Repository, resolveProvider remote.ProviderFunc, releaseConfig config.ReleaseConfig, actionName string, dryRun bool) *ReleaseAction
NewRelease creates a new release action. The provider is passed as a resolver, not a value: everything up to the push -- prepared-notes lookup, version divergence check, the whole dry-run -- is local, and used to be unreachable in a repository without a remote (issue #227).
type ReleaseCommitAction ¶
type ReleaseCommitAction struct {
// contains filtered or unexported fields
}
ReleaseCommitAction commits prepared release notes
func NewReleaseCommit ¶
func NewReleaseCommit(repo *vcs.Repository, dryRun bool) *ReleaseCommitAction
NewReleaseCommit creates a new release commit action
type ReleasePrepareAction ¶
type ReleasePrepareAction struct {
// contains filtered or unexported fields
}
ReleasePrepareAction prepares release notes for human review.
It carries no remote provider: every step reads the local repository (git log, tags, version files) and the merged-PR list comes from the gh CLI, so preparing release notes must work in a repository without a remote -- building the provider up front made it fail before any of that ran (issue #227).
func NewReleasePrepare ¶
func NewReleasePrepare(repo *vcs.Repository, releaseConfig config.ReleaseConfig, dryRun bool) *ReleasePrepareAction
NewReleasePrepare creates a new release prepare action
type ReleasePreviewAction ¶
type ReleasePreviewAction struct {
// contains filtered or unexported fields
}
ReleasePreviewAction shows what will happen during release
func NewReleasePreview ¶
func NewReleasePreview(repo *vcs.Repository, releaseConfig config.ReleaseConfig, dryRun bool) *ReleasePreviewAction
NewReleasePreview creates a new release preview action
type TagCreateAction ¶
type TagCreateAction struct {
// contains filtered or unexported fields
}
TagCreateAction creates and optionally pushes a git tag
func NewTagCreate ¶
func NewTagCreate(repo *vcs.Repository, tagConfig config.TagConfig, dryRun bool) *TagCreateAction
NewTagCreate creates a new tag create action
type TagDeleteAction ¶
type TagDeleteAction struct {
// contains filtered or unexported fields
}
TagDeleteAction deletes a git tag locally and optionally from remote
func NewTagDelete ¶
func NewTagDelete(repo *vcs.Repository, tagConfig config.TagConfig, tagName string, remote, force, dryRun bool) *TagDeleteAction
NewTagDelete creates a new tag delete action
type TagListAction ¶
type TagListAction struct {
// contains filtered or unexported fields
}
TagListAction lists git tags with filtering options
func NewTagList ¶
func NewTagList(repo *vcs.Repository, tagConfig config.TagConfig, limit int, pattern string, verbose bool) *TagListAction
NewTagList creates a new tag list action
type TagPrepareAction ¶
type TagPrepareAction struct {
// contains filtered or unexported fields
}
TagPrepareAction prepares a tag for human review before creation
func NewTagPrepare ¶
func NewTagPrepare(repo *vcs.Repository, tagConfig config.TagConfig, dryRun bool) *TagPrepareAction
NewTagPrepare creates a new tag prepare action
type TagPreviewAction ¶
type TagPreviewAction struct {
// contains filtered or unexported fields
}
TagPreviewAction shows what will happen during tag creation
func NewTagPreview ¶
func NewTagPreview(repo *vcs.Repository, tagConfig config.TagConfig) *TagPreviewAction
NewTagPreview creates a new tag preview action
type VersionState ¶
type VersionState struct {
LastTag string // "v2.1.3", empty when the repo has no tag
TagVersion string // "2.1.3", empty when there is no tag or it is not semver
FileVersion string // VERSION file contents, empty when unreadable
}
VersionState reconciles the two places the release flow can read a "current version" from: the VERSION file (what commitizen bumps) and the latest git tag (what was actually released). They can disagree -- a tag cut outside the flow, or a bump commit that never got tagged -- and computing the next version from the wrong one yields a version below the latest tag (issue #185). The tag is the source of truth; a disagreement is reported, never silently resolved.
func ResolveVersion ¶
func ResolveVersion(workDir string) VersionState
ResolveVersion reads both sources and returns their reconciliation.
func (VersionState) Current ¶
func (s VersionState) Current() string
Current returns the version the release flow must compute from: the latest tag, falling back to the version files only when nothing was ever tagged.
func (VersionState) Diverged ¶
func (s VersionState) Diverged() bool
Diverged reports whether the version files disagree with the latest tag.
func (VersionState) DivergenceError ¶
func (s VersionState) DivergenceError() error
DivergenceError names both values and the way out, or nil when they agree.
func (VersionState) FilesAhead ¶
func (s VersionState) FilesAhead() bool
FilesAhead reports a version bump that landed in the files but was never tagged -- the state `cidx release tag create` exists to close.
func (VersionState) LastTagDisplay ¶
func (s VersionState) LastTagDisplay() string
LastTagDisplay returns the latest tag, or "(none)" when the repo has none.
type WorkflowListAction ¶
type WorkflowListAction struct {
// contains filtered or unexported fields
}
WorkflowListAction lists workflow runs.
It lists a named workflow's runs, and -- with no name -- the runs of every workflow on one branch. That second view is what you want when a check has just failed and you do not yet know which workflow owns it: the failing check names a job, and having to name the workflow file before being allowed to look is what sent this question to `gh` (issue #342).
The runs come from the provider rather than from `gh api`, so the listing speaks the same client, the same repository resolution and the same identifier as the `watch` and `rerun` commands beside it, and works on GitLab.
func NewWorkflowList ¶
func NewWorkflowList(provider remote.Provider, workflow, branch string, limit int, verbose bool) *WorkflowListAction
NewWorkflowList creates a new workflow list action. Exactly one of workflow and branch is expected to be set; setting both narrows to that workflow's runs on that branch, which is a legitimate, if narrower, question.
type WorkflowRerunAction ¶
type WorkflowRerunAction struct {
// contains filtered or unexported fields
}
WorkflowRerunAction restarts a run, or only the jobs of it that failed.
It closes the recovery half of the workflow loop: a job that dies pulling an image (`read: connection reset by peer`, run #724 in issue #342) failed on the infrastructure, not on the change, and the only way back was `gh run rerun --failed` -- the one step that still had to leave cidx, reached for precisely when something has just gone wrong.
func NewWorkflowRerun ¶
func NewWorkflowRerun(provider remote.Provider, runID string, failedOnly bool) *WorkflowRerunAction
NewWorkflowRerun creates a workflow rerun action. runID must already be resolved by the caller (the CLI defaults it to the latest run on the current branch).
func (*WorkflowRerunAction) Execute ¶
func (a *WorkflowRerunAction) Execute(ctx context.Context) error
Execute restarts the run and names the command that follows it.
The run is read first, for two reasons: a wrong identifier is reported as such -- `list` prints a run number next to the ID and handing over the wrong one is the mistake #291 was about -- and `--failed` on a run with no failed job is refused here rather than as the provider's bare 403.
type WorkflowRunAction ¶
type WorkflowRunAction struct {
// contains filtered or unexported fields
}
WorkflowRunAction triggers a workflow on a ref and, by default, watches the run it started. It closes the last hole in the dogfooding loop: changing a workflow used to mean dropping to `gh workflow run` to try it (issue #266).
func NewWorkflowRun ¶
func NewWorkflowRun(provider remote.Provider, workflow, ref string, inputs map[string]string, watch bool) *WorkflowRunAction
NewWorkflowRun creates a workflow run action. ref must already be resolved by the caller (the CLI defaults it to the current branch).
type WorkflowWatchAction ¶
type WorkflowWatchAction struct {
// contains filtered or unexported fields
}
WorkflowWatchAction watches a single workflow run, selected by branch, tag or run ID. It complements `cidx pr watch` by supporting non-PR branches such as direct pushes to main (issue #125) and tag pushes (issue #223).
func NewWorkflowWatch ¶
func NewWorkflowWatch(provider remote.Provider, branch, tag, runID string, quiet bool) *WorkflowWatchAction
NewWorkflowWatch creates a new workflow watch action.
Exactly one of branch, tag or runID should be set. A branch or a tag resolves to the most recent run on that ref; a run ID watches that run directly. When several are set, the most specific wins: runID, then tag, then branch.
Source Files
¶
- artifact.go
- artifact_download.go
- commit_push_watch.go
- cpw_plan.go
- editor.go
- module_major.go
- pr.go
- pr_edit.go
- release.go
- release_commit.go
- release_prepare.go
- release_preview.go
- tag_create.go
- tag_delete.go
- tag_list.go
- tag_prepare.go
- tag_preview.go
- verify.go
- version.go
- watch_target.go
- workflow_display.go
- workflow_list.go
- workflow_rerun.go
- workflow_run.go
- workflow_watch.go