Document GitRepository API v1beta2 spec

Signed-off-by: Hidde Beydals <hello@hidde.co>
This commit is contained in:
Hidde Beydals 2022-02-08 16:51:27 +01:00
parent 691bd50143
commit 0d3170f193
7 changed files with 1171 additions and 254 deletions

View File

@ -29,85 +29,116 @@ const (
// GitRepositoryKind is the string representation of a GitRepository.
GitRepositoryKind = "GitRepository"
// GoGitImplementation represents the go-git Git implementation kind.
// GoGitImplementation for performing Git operations using go-git.
GoGitImplementation = "go-git"
// LibGit2Implementation represents the git2go Git implementation kind.
// LibGit2Implementation for performing Git operations using libgit2.
LibGit2Implementation = "libgit2"
)
const (
// IncludeUnavailableCondition indicates one of the includes is not available. For example, because it does not
// exist, or does not have an Artifact.
// This is a "negative polarity" or "abnormal-true" type, and is only present on the resource if it is True.
// IncludeUnavailableCondition indicates one of the includes is not
// available. For example, because it does not exist, or does not have an
// Artifact.
// This is a "negative polarity" or "abnormal-true" type, and is only
// present on the resource if it is True.
IncludeUnavailableCondition string = "IncludeUnavailable"
)
// GitRepositorySpec defines the desired state of a Git repository.
// GitRepositorySpec specifies the required configuration to produce an
// Artifact for a Git repository.
type GitRepositorySpec struct {
// The repository URL, can be a HTTP/S or SSH address.
// URL specifies the Git repository URL, can be an HTTP/S or SSH address.
// +kubebuilder:validation:Pattern="^(http|https|ssh)://"
// +required
URL string `json:"url"`
// The secret name containing the Git credentials.
// For HTTPS repositories the secret must contain username and password fields.
// For SSH repositories the secret must contain 'identity', 'identity.pub' and 'known_hosts' fields.
// SecretRef specifies the Secret containing authentication credentials for
// the GitRepository.
// For HTTPS repositories the Secret must contain 'username' and 'password'
// fields.
// For SSH repositories the Secret must contain 'identity', 'identity.pub'
// and 'known_hosts' fields.
// +optional
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
// The interval at which to check for repository updates.
// Interval at which to check the GitRepository for updates.
// +required
Interval metav1.Duration `json:"interval"`
// The timeout for remote Git operations like cloning, defaults to 60s.
// Timeout for Git operations like cloning, defaults to 60s.
// +kubebuilder:default="60s"
// +optional
Timeout *metav1.Duration `json:"timeout,omitempty"`
// The Git reference to checkout and monitor for changes, defaults to
// master branch.
// Reference specifies the Git reference to resolve and monitor for
// changes, defaults to the 'master' branch.
// +optional
Reference *GitRepositoryRef `json:"ref,omitempty"`
// Verification defines the configuration to verify the OpenPGP signature for the Git commit HEAD points to.
// Verification specifies the configuration to verify the Git commit
// signature(s).
// +optional
Verification *GitRepositoryVerification `json:"verify,omitempty"`
// Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore).
// If not provided, a default will be used, consult the documentation for your version to find out what those are.
// Ignore overrides the set of excluded patterns in the .sourceignore format
// (which is the same as .gitignore). If not provided, a default will be used,
// consult the documentation for your version to find out what those are.
// +optional
Ignore *string `json:"ignore,omitempty"`
// Suspend tells the controller to suspend the reconciliation of this source.
// This flag tells the controller to suspend the reconciliation of this source.
// Suspend tells the controller to suspend the reconciliation of this
// GitRepository.
// +optional
Suspend bool `json:"suspend,omitempty"`
// Determines which git client library to use.
// Defaults to go-git, valid values are ('go-git', 'libgit2').
// GitImplementation specifies which Git client library implementation to
// use. Defaults to 'go-git', valid values are ('go-git', 'libgit2').
// +kubebuilder:validation:Enum=go-git;libgit2
// +kubebuilder:default:=go-git
// +optional
GitImplementation string `json:"gitImplementation,omitempty"`
// When enabled, after the clone is created, initializes all submodules within, using their default settings.
// RecurseSubmodules enables the initialization of all submodules within
// the GitRepository as cloned from the URL, using their default settings.
// This option is available only when using the 'go-git' GitImplementation.
// +optional
RecurseSubmodules bool `json:"recurseSubmodules,omitempty"`
// Include defines a list of GitRepository resources which artifacts should be included in the artifact produced for
// this resource.
// Include specifies a list of GitRepository resources which Artifacts
// should be included in the Artifact produced for this GitRepository.
Include []GitRepositoryInclude `json:"include,omitempty"`
// AccessFrom defines an Access Control List for allowing cross-namespace references to this object.
// AccessFrom specifies an Access Control List for allowing cross-namespace
// references to this object.
// +optional
AccessFrom *acl.AccessFrom `json:"accessFrom,omitempty"`
}
// GitRepositoryInclude specifies a reference to a GitRepository which Artifact
// (sub-)contents must be included, and where they should be placed.
type GitRepositoryInclude struct {
// GitRepositoryRef specifies the GitRepository which Artifact contents
// must be included.
GitRepositoryRef meta.LocalObjectReference `json:"repository"`
// FromPath specifies the path to copy contents from, defaults to the root
// of the Artifact.
// +optional
FromPath string `json:"fromPath"`
// ToPath specifies the path to copy contents to, defaults to the name of
// the GitRepositoryRef.
// +optional
ToPath string `json:"toPath"`
}
// GetFromPath returns the specified FromPath.
func (in *GitRepositoryInclude) GetFromPath() string {
return in.FromPath
}
// GetToPath returns the specified ToPath, falling back to the name of the
// GitRepositoryRef.
func (in *GitRepositoryInclude) GetToPath() string {
if in.ToPath == "" {
return in.GitRepositoryRef.Name
@ -115,52 +146,48 @@ func (in *GitRepositoryInclude) GetToPath() string {
return in.ToPath
}
// GitRepositoryInclude defines a source with a from and to path.
type GitRepositoryInclude struct {
// Reference to a GitRepository to include.
GitRepositoryRef meta.LocalObjectReference `json:"repository"`
// The path to copy contents from, defaults to the root directory.
// +optional
FromPath string `json:"fromPath"`
// The path to copy contents to, defaults to the name of the source ref.
// +optional
ToPath string `json:"toPath"`
}
// GitRepositoryRef defines the Git ref used for pull and checkout operations.
// GitRepositoryRef specifies the Git reference to resolve and checkout.
type GitRepositoryRef struct {
// The Git branch to checkout, defaults to master.
// Branch to check out, defaults to 'master' if no other field is defined.
//
// When GitRepositorySpec.GitImplementation is set to 'go-git', a shallow
// clone of the specified branch is performed.
// +optional
Branch string `json:"branch,omitempty"`
// The Git tag to checkout, takes precedence over Branch.
// Tag to check out, takes precedence over Branch.
// +optional
Tag string `json:"tag,omitempty"`
// The Git tag semver expression, takes precedence over Tag.
// SemVer tag expression to check out, takes precedence over Tag.
// +optional
SemVer string `json:"semver,omitempty"`
// The Git commit SHA to checkout, if specified Tag filters will be ignored.
// Commit SHA to check out, takes precedence over all reference fields.
//
// When GitRepositorySpec.GitImplementation is set to 'go-git', this can be
// combined with Branch to shallow clone the branch, in which the commit is
// expected to exist.
// +optional
Commit string `json:"commit,omitempty"`
}
// GitRepositoryVerification defines the OpenPGP signature verification process.
// GitRepositoryVerification specifies the Git commit signature verification
// strategy.
type GitRepositoryVerification struct {
// Mode describes what Git object should be verified, currently ('head').
// Mode specifies what Git object should be verified, currently ('head').
// +kubebuilder:validation:Enum=head
Mode string `json:"mode"`
// SecretRef containing the public keys of all trusted Git authors.
// SecretRef specifies the Secret containing the public keys of trusted Git
// authors.
SecretRef meta.LocalObjectReference `json:"secretRef,omitempty"`
}
// GitRepositoryStatus defines the observed state of a Git repository.
// GitRepositoryStatus records the observed state of a Git repository.
type GitRepositoryStatus struct {
// ObservedGeneration is the last observed generation.
// ObservedGeneration is the last observed generation of the GitRepository
// object.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
@ -168,15 +195,18 @@ type GitRepositoryStatus struct {
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
// URL is the fetch link for the artifact output of the last repository sync.
// URL is the dynamic fetch link for the latest Artifact.
// It is provided on a "best effort" basis, and using the precise
// GitRepositoryStatus.Artifact data is recommended.
// +optional
URL string `json:"url,omitempty"`
// Artifact represents the output of the last successful repository sync.
// Artifact represents the last successful GitRepository reconciliation.
// +optional
Artifact *Artifact `json:"artifact,omitempty"`
// IncludedArtifacts represents the included artifacts from the last successful repository sync.
// IncludedArtifacts contains a list of the last successfully included
// Artifacts as instructed by GitRepositorySpec.Include.
// +optional
IncludedArtifacts []*Artifact `json:"includedArtifacts,omitempty"`
@ -184,10 +214,12 @@ type GitRepositoryStatus struct {
}
const (
// GitOperationSucceedReason represents the fact that the git clone, pull and checkout operations succeeded.
GitOperationSucceedReason string = "GitOperationSucceed"
// GitOperationSucceedReason signals that a Git operation (e.g. clone,
// checkout, etc.) succeeded.
GitOperationSucceedReason string = "GitOperationSucceeded"
// GitOperationFailedReason represents the fact that the git clone, pull or checkout operations failed.
// GitOperationFailedReason signals that a Git operation (e.g. clone,
// checkout, etc.) failed.
GitOperationFailedReason string = "GitOperationFailed"
)
@ -201,28 +233,18 @@ func (in *GitRepository) SetConditions(conditions []metav1.Condition) {
in.Status.Conditions = conditions
}
// GetRequeueAfter returns the duration after which the source must be reconciled again.
// GetRequeueAfter returns the duration after which the GitRepository must be
// reconciled again.
func (in GitRepository) GetRequeueAfter() time.Duration {
return in.Spec.Interval.Duration
}
// GetInterval returns the interval at which the source is reconciled.
// Deprecated: use GetRequeueAfter instead.
func (in GitRepository) GetInterval() metav1.Duration {
return in.Spec.Interval
}
// GetArtifact returns the latest artifact from the source if present in the status sub-resource.
// GetArtifact returns the latest Artifact from the GitRepository if present in
// the status sub-resource.
func (in *GitRepository) GetArtifact() *Artifact {
return in.Status.Artifact
}
// GetStatusConditions returns a pointer to the Status.Conditions slice.
// Deprecated: use GetConditions instead.
func (in *GitRepository) GetStatusConditions() *[]metav1.Condition {
return &in.Status.Conditions
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:storageversion
@ -234,7 +256,7 @@ func (in *GitRepository) GetStatusConditions() *[]metav1.Condition {
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// GitRepository is the Schema for the gitrepositories API
// GitRepository is the Schema for the gitrepositories API.
type GitRepository struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
@ -244,7 +266,7 @@ type GitRepository struct {
Status GitRepositoryStatus `json:"status,omitempty"`
}
// GitRepositoryList contains a list of GitRepository
// GitRepositoryList contains a list of GitRepository objects.
// +kubebuilder:object:root=true
type GitRepositoryList struct {
metav1.TypeMeta `json:",inline"`

View File

@ -365,7 +365,7 @@ spec:
name: v1beta2
schema:
openAPIV3Schema:
description: GitRepository is the Schema for the gitrepositories API
description: GitRepository is the Schema for the gitrepositories API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
@ -380,10 +380,11 @@ spec:
metadata:
type: object
spec:
description: GitRepositorySpec defines the desired state of a Git repository.
description: GitRepositorySpec specifies the required configuration to
produce an Artifact for a Git repository.
properties:
accessFrom:
description: AccessFrom defines an Access Control List for allowing
description: AccessFrom specifies an Access Control List for allowing
cross-namespace references to this object.
properties:
namespaceSelectors:
@ -411,8 +412,9 @@ spec:
type: object
gitImplementation:
default: go-git
description: Determines which git client library to use. Defaults
to go-git, valid values are ('go-git', 'libgit2').
description: GitImplementation specifies which Git client library
implementation to use. Defaults to 'go-git', valid values are ('go-git',
'libgit2').
enum:
- go-git
- libgit2
@ -424,18 +426,20 @@ spec:
to find out what those are.
type: string
include:
description: Include defines a list of GitRepository resources which
artifacts should be included in the artifact produced for this resource.
description: Include specifies a list of GitRepository resources which
Artifacts should be included in the Artifact produced for this GitRepository.
items:
description: GitRepositoryInclude defines a source with a from and
to path.
description: GitRepositoryInclude specifies a reference to a GitRepository
which Artifact (sub-)contents must be included, and where they
should be placed.
properties:
fromPath:
description: The path to copy contents from, defaults to the
root directory.
description: FromPath specifies the path to copy contents from,
defaults to the root of the Artifact.
type: string
repository:
description: Reference to a GitRepository to include.
description: GitRepositoryRef specifies the GitRepository which
Artifact contents must be included.
properties:
name:
description: Name of the referent.
@ -444,45 +448,52 @@ spec:
- name
type: object
toPath:
description: The path to copy contents to, defaults to the name
of the source ref.
description: ToPath specifies the path to copy contents to,
defaults to the name of the GitRepositoryRef.
type: string
required:
- repository
type: object
type: array
interval:
description: The interval at which to check for repository updates.
description: Interval at which to check the GitRepository for updates.
type: string
recurseSubmodules:
description: When enabled, after the clone is created, initializes
all submodules within, using their default settings. This option
is available only when using the 'go-git' GitImplementation.
description: RecurseSubmodules enables the initialization of all submodules
within the GitRepository as cloned from the URL, using their default
settings. This option is available only when using the 'go-git'
GitImplementation.
type: boolean
ref:
description: The Git reference to checkout and monitor for changes,
defaults to master branch.
description: Reference specifies the Git reference to resolve and
monitor for changes, defaults to the 'master' branch.
properties:
branch:
description: The Git branch to checkout, defaults to master.
description: "Branch to check out, defaults to 'master' if no
other field is defined. \n When GitRepositorySpec.GitImplementation
is set to 'go-git', a shallow clone of the specified branch
is performed."
type: string
commit:
description: The Git commit SHA to checkout, if specified Tag
filters will be ignored.
description: "Commit SHA to check out, takes precedence over all
reference fields. \n When GitRepositorySpec.GitImplementation
is set to 'go-git', this can be combined with Branch to shallow
clone the branch, in which the commit is expected to exist."
type: string
semver:
description: The Git tag semver expression, takes precedence over
Tag.
description: SemVer tag expression to check out, takes precedence
over Tag.
type: string
tag:
description: The Git tag to checkout, takes precedence over Branch.
description: Tag to check out, takes precedence over Branch.
type: string
type: object
secretRef:
description: The secret name containing the Git credentials. For HTTPS
repositories the secret must contain username and password fields.
For SSH repositories the secret must contain 'identity', 'identity.pub'
and 'known_hosts' fields.
description: SecretRef specifies the Secret containing authentication
credentials for the GitRepository. For HTTPS repositories the Secret
must contain 'username' and 'password' fields. For SSH repositories
the Secret must contain 'identity', 'identity.pub' and 'known_hosts'
fields.
properties:
name:
description: Name of the referent.
@ -492,31 +503,31 @@ spec:
type: object
suspend:
description: Suspend tells the controller to suspend the reconciliation
of this source. This flag tells the controller to suspend the reconciliation
of this source.
of this GitRepository.
type: boolean
timeout:
default: 60s
description: The timeout for remote Git operations like cloning, defaults
to 60s.
description: Timeout for Git operations like cloning, defaults to
60s.
type: string
url:
description: The repository URL, can be a HTTP/S or SSH address.
description: URL specifies the Git repository URL, can be an HTTP/S
or SSH address.
pattern: ^(http|https|ssh)://
type: string
verify:
description: Verification defines the configuration to verify the
OpenPGP signature for the Git commit HEAD points to.
description: Verification specifies the configuration to verify the
Git commit signature(s).
properties:
mode:
description: Mode describes what Git object should be verified,
description: Mode specifies what Git object should be verified,
currently ('head').
enum:
- head
type: string
secretRef:
description: SecretRef containing the public keys of all trusted
Git authors.
description: SecretRef specifies the Secret containing the public
keys of trusted Git authors.
properties:
name:
description: Name of the referent.
@ -534,11 +545,11 @@ spec:
status:
default:
observedGeneration: -1
description: GitRepositoryStatus defines the observed state of a Git repository.
description: GitRepositoryStatus records the observed state of a Git repository.
properties:
artifact:
description: Artifact represents the output of the last successful
repository sync.
description: Artifact represents the last successful GitRepository
reconciliation.
properties:
checksum:
description: Checksum is the SHA256 checksum of the Artifact file.
@ -639,8 +650,8 @@ spec:
type: object
type: array
includedArtifacts:
description: IncludedArtifacts represents the included artifacts from
the last successful repository sync.
description: IncludedArtifacts contains a list of the last successfully
included Artifacts as instructed by GitRepositorySpec.Include.
items:
description: Artifact represents the output of a Source reconciliation.
properties:
@ -681,12 +692,14 @@ spec:
be detected.
type: string
observedGeneration:
description: ObservedGeneration is the last observed generation.
description: ObservedGeneration is the last observed generation of
the GitRepository object.
format: int64
type: integer
url:
description: URL is the fetch link for the artifact output of the
last repository sync.
description: URL is the dynamic fetch link for the latest Artifact.
It is provided on a "best effort" basis, and using the precise GitRepositoryStatus.Artifact
data is recommended.
type: string
type: object
type: object

View File

@ -53,9 +53,9 @@ import (
"github.com/fluxcd/source-controller/pkg/sourceignore"
)
// gitRepoReadyConditions contains all the conditions information needed
// for GitRepository Ready status conditions summary calculation.
var gitRepoReadyConditions = summarize.Conditions{
// gitRepositoryReadyCondition contains the information required to summarize a
// v1beta2.GitRepository Ready Condition.
var gitRepositoryReadyCondition = summarize.Conditions{
Target: meta.ReadyCondition,
Owned: []string{
sourcev1.SourceVerifiedCondition,
@ -88,7 +88,7 @@ var gitRepoReadyConditions = summarize.Conditions{
// +kubebuilder:rbac:groups=source.toolkit.fluxcd.io,resources=gitrepositories/finalizers,verbs=get;create;update;patch;delete
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
// GitRepositoryReconciler reconciles a GitRepository object
// GitRepositoryReconciler reconciles a v1beta2.GitRepository object.
type GitRepositoryReconciler struct {
client.Client
kuberecorder.EventRecorder
@ -104,9 +104,9 @@ type GitRepositoryReconcilerOptions struct {
DependencyRequeueInterval time.Duration
}
// gitRepoReconcilerFunc is the function type for all the Git repository
// reconciler functions.
type gitRepoReconcilerFunc func(ctx context.Context, obj *sourcev1.GitRepository, artifact *sourcev1.Artifact, includes *artifactSet, dir string) (sreconcile.Result, error)
// gitRepositoryReconcileFunc is the function type for all the
// v1beta2.GitRepository (sub)reconcile functions.
type gitRepositoryReconcileFunc func(ctx context.Context, obj *sourcev1.GitRepository, artifact *sourcev1.Artifact, includes *artifactSet, dir string) (sreconcile.Result, error)
func (r *GitRepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
return r.SetupWithManagerAndOptions(mgr, GitRepositoryReconcilerOptions{})
@ -156,7 +156,7 @@ func (r *GitRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reques
defer func() {
summarizeHelper := summarize.NewHelper(r.EventRecorder, patchHelper)
summarizeOpts := []summarize.Option{
summarize.WithConditions(gitRepoReadyConditions),
summarize.WithConditions(gitRepositoryReadyCondition),
summarize.WithReconcileResult(recResult),
summarize.WithReconcileError(retErr),
summarize.WithIgnoreNotFound(),
@ -164,7 +164,7 @@ func (r *GitRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reques
summarize.RecordContextualError,
summarize.RecordReconcileReq,
),
summarize.WithResultBuilder(sreconcile.AlwaysRequeueResultBuilder{RequeueAfter: obj.GetInterval().Duration}),
summarize.WithResultBuilder(sreconcile.AlwaysRequeueResultBuilder{RequeueAfter: obj.GetRequeueAfter()}),
}
result, retErr = summarizeHelper.SummarizeAndPatch(ctx, obj, summarizeOpts...)
@ -188,7 +188,7 @@ func (r *GitRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reques
}
// Reconcile actual object
reconcilers := []gitRepoReconcilerFunc{
reconcilers := []gitRepositoryReconcileFunc{
r.reconcileStorage,
r.reconcileSource,
r.reconcileInclude,
@ -198,17 +198,15 @@ func (r *GitRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reques
return
}
// reconcile steps iterates through the actual reconciliation tasks for objec,
// it returns early on the first step that returns ResultRequeue or produces an
// error.
func (r *GitRepositoryReconciler) reconcile(ctx context.Context, obj *sourcev1.GitRepository, reconcilers []gitRepoReconcilerFunc) (sreconcile.Result, error) {
// reconcile iterates through the gitRepositoryReconcileFunc tasks for the
// object. It returns early on the first call that returns
// reconcile.ResultRequeue, or produces an error.
func (r *GitRepositoryReconciler) reconcile(ctx context.Context, obj *sourcev1.GitRepository, reconcilers []gitRepositoryReconcileFunc) (sreconcile.Result, error) {
// Mark as reconciling if generation differs
if obj.Generation != obj.Status.ObservedGeneration {
conditions.MarkReconciling(obj, "NewGeneration", "reconciling new object generation (%d)", obj.Generation)
}
var artifact sourcev1.Artifact
var includes artifactSet
// Create temp dir for Git clone
tmpDir, err := util.TempDirForObj("", obj)
if err != nil {
@ -217,11 +215,20 @@ func (r *GitRepositoryReconciler) reconcile(ctx context.Context, obj *sourcev1.G
Reason: sourcev1.StorageOperationFailedReason,
}
}
defer os.RemoveAll(tmpDir)
defer func() {
if err = os.RemoveAll(tmpDir); err != nil {
ctrl.LoggerFrom(ctx).Error(err, "failed to remove temporary working directory")
}
}()
// Run the sub-reconcilers and build the result of reconciliation.
var res sreconcile.Result
var resErr error
var (
artifact sourcev1.Artifact
includes artifactSet
res sreconcile.Result
resErr error
)
for _, rec := range reconcilers {
recResult, err := rec(ctx, obj, &artifact, &includes, tmpDir)
// Exit immediately on ResultRequeue.
@ -241,13 +248,18 @@ func (r *GitRepositoryReconciler) reconcile(ctx context.Context, obj *sourcev1.G
return res, resErr
}
// reconcileStorage ensures the current state of the storage matches the desired and previously observed state.
// reconcileStorage ensures the current state of the storage matches the
// desired and previously observed state.
//
// All artifacts for the resource except for the current one are garbage collected from the storage.
// If the artifact in the Status object of the resource disappeared from storage, it is removed from the object.
// If the object does not have an artifact in its Status object, a v1beta1.ArtifactUnavailableCondition is set.
// If the hostname of any of the URLs on the object do not match the current storage server hostname, they are updated.
func (r *GitRepositoryReconciler) reconcileStorage(ctx context.Context, obj *sourcev1.GitRepository, artifact *sourcev1.Artifact, includes *artifactSet, dir string) (sreconcile.Result, error) {
// All Artifacts for the object except for the current one in the Status are
// garbage collected from the Storage.
// If the Artifact in the Status of the object disappeared from the Storage,
// it is removed from the object.
// If the object does not have an Artifact in its Status, a Reconciling
// condition is added.
// The hostname of any URL in the Status of the object are updated, to ensure
// they match the Storage server hostname of current runtime.
func (r *GitRepositoryReconciler) reconcileStorage(ctx context.Context, obj *sourcev1.GitRepository, _ *sourcev1.Artifact, _ *artifactSet, _ string) (sreconcile.Result, error) {
// Garbage collect previous advertised artifact(s) from storage
_ = r.garbageCollect(ctx, obj)
@ -271,19 +283,25 @@ func (r *GitRepositoryReconciler) reconcileStorage(ctx context.Context, obj *sou
return sreconcile.ResultSuccess, nil
}
// reconcileSource ensures the upstream Git repository can be reached and checked out using the declared configuration,
// and observes its state.
// reconcileSource ensures the upstream Git repository and reference can be
// cloned and checked out using the specified configuration, and observes its
// state.
//
// The repository is checked out to the given dir using the defined configuration, and in case of an error during the
// checkout process (including transient errors), it records v1beta1.FetchFailedCondition=True and returns early.
// On a successful checkout it removes v1beta1.FetchFailedCondition, and compares the current revision of HEAD to the
// artifact on the object, and records v1beta1.ArtifactOutdatedCondition if they differ.
// If instructed, the signature of the commit is verified if and recorded as v1beta1.SourceVerifiedCondition. If the
// signature can not be verified or the verification fails, the Condition=False and it returns early.
// If both the checkout and signature verification are successful, the given artifact pointer is set to a new artifact
// with the available metadata.
func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context,
obj *sourcev1.GitRepository, artifact *sourcev1.Artifact, _ *artifactSet, dir string) (sreconcile.Result, error) {
// The repository is cloned to the given dir, using the specified configuration
// to check out the reference. In case of an error during this process
// (including transient errors), it records v1beta2.FetchFailedCondition=True
// and returns early.
// On a successful checkout, it removes v1beta2.FetchFailedCondition and
// compares the current revision of HEAD to the revision of the Artifact in the
// Status of the object. It records v1beta2.ArtifactOutdatedCondition=True when
// they differ.
// If specified, the signature of the Git commit is verified. If the signature
// can not be verified or the verification fails, it records
// v1beta2.SourceVerifiedCondition=False and returns early. When successful,
// it records v1beta2.SourceVerifiedCondition=True.
// When all the above is successful, the given Artifact pointer is set to a new
// Artifact composed out of the gathered Git metadata.
func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context, obj *sourcev1.GitRepository, artifact *sourcev1.Artifact, _ *artifactSet, dir string) (sreconcile.Result, error) {
// Configure authentication strategy to access the source
var authOpts *git.AuthOptions
var err error
@ -374,15 +392,17 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context,
return sreconcile.ResultSuccess, nil
}
// reconcileArtifact archives a new artifact to the storage, if the current observation on the object does not match the
// given data.
// reconcileArtifact archives a new Artifact to the Storage, if the current
// (Status) data on the object does not match the given.
//
// The inspection of the given data to the object is differed, ensuring any stale observations as
// v1beta1.ArtifactUnavailableCondition and v1beta1.ArtifactOutdatedCondition are always deleted.
// If the given artifact and/or includes do not differ from the object's current, it returns early.
// Source ignore patterns are loaded, and the given directory is archived.
// On a successful archive, the artifact and includes in the status of the given object are set, and the symlink in the
// storage is updated to its path.
// The inspection of the given data to the object is differed, ensuring any
// stale observations like v1beta2.ArtifactOutdatedCondition are removed.
// If the given Artifact and/or artifactSet (includes) do not differ from the
// object's current, it returns early.
// Source ignore patterns are loaded, and the given directory is archived while
// taking these patterns into account.
// On a successful archive, the Artifact and Includes in the Status of the
// object are set, and the symlink in the Storage is updated to its path.
func (r *GitRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *sourcev1.GitRepository, artifact *sourcev1.Artifact, includes *artifactSet, dir string) (sreconcile.Result, error) {
// Always restore the Ready condition in case it got removed due to a transient error
defer func() {
@ -475,13 +495,19 @@ func (r *GitRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
return sreconcile.ResultSuccess, nil
}
// reconcileInclude reconciles the declared includes from the object by copying their artifact (sub)contents to the
// declared paths in the given directory.
// reconcileInclude reconciles the on the object specified
// v1beta2.GitRepositoryInclude list by copying their Artifact (sub)contents to
// the specified paths in the given directory.
//
// If an include is unavailable, it marks the object with v1beta1.IncludeUnavailableCondition and returns early.
// If the copy operations are successful, it deletes the v1beta1.IncludeUnavailableCondition from the object.
// If the artifactSet differs from the current set, it marks the object with v1beta1.ArtifactOutdatedCondition.
func (r *GitRepositoryReconciler) reconcileInclude(ctx context.Context, obj *sourcev1.GitRepository, _ *sourcev1.Artifact, includes *artifactSet, dir string) (sreconcile.Result, error) {
// When one of the includes is unavailable, it marks the object with
// v1beta2.IncludeUnavailableCondition=True and returns early.
// When the copy operations are successful, it removes the
// v1beta2.IncludeUnavailableCondition from the object.
// When the composed artifactSet differs from the current set in the Status of
// the object, it marks the object with v1beta2.ArtifactOutdatedCondition=True.
func (r *GitRepositoryReconciler) reconcileInclude(ctx context.Context, obj *sourcev1.GitRepository,
_ *sourcev1.Artifact, includes *artifactSet, dir string) (sreconcile.Result, error) {
artifacts := make(artifactSet, len(obj.Spec.Include))
for i, incl := range obj.Spec.Include {
// Do this first as it is much cheaper than copy operations
@ -542,25 +568,16 @@ func (r *GitRepositoryReconciler) reconcileInclude(ctx context.Context, obj *sou
return sreconcile.ResultSuccess, nil
}
// reconcileDelete handles the delete of an object. It first garbage collects all artifacts for the object from the
// artifact storage, if successful, the finalizer is removed from the object.
func (r *GitRepositoryReconciler) reconcileDelete(ctx context.Context, obj *sourcev1.GitRepository) (sreconcile.Result, error) {
// Garbage collect the resource's artifacts
if err := r.garbageCollect(ctx, obj); err != nil {
// Return the error so we retry the failed garbage collection
return sreconcile.ResultEmpty, err
}
// Remove our finalizer from the list
controllerutil.RemoveFinalizer(obj, sourcev1.SourceFinalizer)
// Stop reconciliation as the object is being deleted
return sreconcile.ResultEmpty, nil
}
// verifyCommitSignature verifies the signature of the given commit if a verification mode is configured on the object.
// verifyCommitSignature verifies the signature of the given Git commit, if a
// verification mode is specified on the object.
// If the signature can not be verified or the verification fails, it records
// v1beta2.SourceVerifiedCondition=False and returns.
// When successful, it records v1beta2.SourceVerifiedCondition=True.
// If no verification mode is specified on the object, the
// v1beta2.SourceVerifiedCondition Condition is removed.
func (r *GitRepositoryReconciler) verifyCommitSignature(ctx context.Context, obj *sourcev1.GitRepository, commit git.Commit) (sreconcile.Result, error) {
// Check if there is a commit verification is configured and remove any old observations if there is none
// Check if there is a commit verification is configured and remove any old
// observations if there is none
if obj.Spec.Verification == nil || obj.Spec.Verification.Mode == "" {
conditions.Delete(obj, sourcev1.SourceVerifiedCondition)
return sreconcile.ResultSuccess, nil
@ -603,9 +620,28 @@ func (r *GitRepositoryReconciler) verifyCommitSignature(ctx context.Context, obj
return sreconcile.ResultSuccess, nil
}
// garbageCollect performs a garbage collection for the given v1beta1.GitRepository. It removes all but the current
// artifact except for when the deletion timestamp is set, which will result in the removal of all artifacts for the
// resource.
// reconcileDelete handles the deletion of the object.
// It first garbage collects all Artifacts for the object from the Storage.
// Removing the finalizer from the object if successful.
func (r *GitRepositoryReconciler) reconcileDelete(ctx context.Context, obj *sourcev1.GitRepository) (sreconcile.Result, error) {
// Garbage collect the resource's artifacts
if err := r.garbageCollect(ctx, obj); err != nil {
// Return the error so we retry the failed garbage collection
return sreconcile.ResultEmpty, err
}
// Remove our finalizer from the list
controllerutil.RemoveFinalizer(obj, sourcev1.SourceFinalizer)
// Stop reconciliation as the object is being deleted
return sreconcile.ResultEmpty, nil
}
// garbageCollect performs a garbage collection for the given object.
//
// It removes all but the current Artifact from the Storage, unless the
// deletion timestamp on the object is set. Which will result in the
// removal of all Artifacts for the objects.
func (r *GitRepositoryReconciler) garbageCollect(ctx context.Context, obj *sourcev1.GitRepository) error {
if !obj.DeletionTimestamp.IsZero() {
if deleted, err := r.Storage.RemoveAll(r.Storage.NewArtifactFor(obj.Kind, obj.GetObjectMeta(), "", "*")); err != nil {
@ -633,9 +669,11 @@ func (r *GitRepositoryReconciler) garbageCollect(ctx context.Context, obj *sourc
return nil
}
// eventLog records event and logs at the same time. This log is different from
// the debug log in the event recorder in the sense that this is a simple log,
// the event recorder debug log contains complete details about the event.
// eventLogf records event and logs at the same time.
//
// This log is different from the debug log in the EventRecorder, in the sense
// that this is a simple log. While the debug log contains complete details
// about the event.
func (r *GitRepositoryReconciler) eventLogf(ctx context.Context, obj runtime.Object, eventType string, reason string, messageFmt string, args ...interface{}) {
msg := fmt.Sprintf(messageFmt, args...)
// Log and emit event.

View File

@ -191,7 +191,7 @@ func TestGitRepositoryReconciler_Reconcile(t *testing.T) {
}, timeout).Should(BeTrue())
// Check if the object status is valid.
condns := &status.Conditions{NegativePolarity: gitRepoReadyConditions.NegativePolarity}
condns := &status.Conditions{NegativePolarity: gitRepositoryReadyCondition.NegativePolarity}
checker := status.NewChecker(testEnv.Client, testEnv.GetScheme(), condns)
checker.CheckErr(ctx, obj)

View File

@ -240,7 +240,7 @@ BucketStatus
</div>
<h3 id="source.toolkit.fluxcd.io/v1beta2.GitRepository">GitRepository
</h3>
<p>GitRepository is the Schema for the gitrepositories API</p>
<p>GitRepository is the Schema for the gitrepositories API.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -303,7 +303,7 @@ string
</em>
</td>
<td>
<p>The repository URL, can be a HTTP/S or SSH address.</p>
<p>URL specifies the Git repository URL, can be an HTTP/S or SSH address.</p>
</td>
</tr>
<tr>
@ -317,9 +317,12 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</td>
<td>
<em>(Optional)</em>
<p>The secret name containing the Git credentials.
For HTTPS repositories the secret must contain username and password fields.
For SSH repositories the secret must contain &lsquo;identity&rsquo;, &lsquo;identity.pub&rsquo; and &lsquo;known_hosts&rsquo; fields.</p>
<p>SecretRef specifies the Secret containing authentication credentials for
the GitRepository.
For HTTPS repositories the Secret must contain &lsquo;username&rsquo; and &lsquo;password&rsquo;
fields.
For SSH repositories the Secret must contain &lsquo;identity&rsquo;, &lsquo;identity.pub&rsquo;
and &lsquo;known_hosts&rsquo; fields.</p>
</td>
</tr>
<tr>
@ -332,7 +335,7 @@ Kubernetes meta/v1.Duration
</em>
</td>
<td>
<p>The interval at which to check for repository updates.</p>
<p>Interval at which to check the GitRepository for updates.</p>
</td>
</tr>
<tr>
@ -346,7 +349,7 @@ Kubernetes meta/v1.Duration
</td>
<td>
<em>(Optional)</em>
<p>The timeout for remote Git operations like cloning, defaults to 60s.</p>
<p>Timeout for Git operations like cloning, defaults to 60s.</p>
</td>
</tr>
<tr>
@ -360,8 +363,8 @@ GitRepositoryRef
</td>
<td>
<em>(Optional)</em>
<p>The Git reference to checkout and monitor for changes, defaults to
master branch.</p>
<p>Reference specifies the Git reference to resolve and monitor for
changes, defaults to the &lsquo;master&rsquo; branch.</p>
</td>
</tr>
<tr>
@ -375,7 +378,8 @@ GitRepositoryVerification
</td>
<td>
<em>(Optional)</em>
<p>Verification defines the configuration to verify the OpenPGP signature for the Git commit HEAD points to.</p>
<p>Verification specifies the configuration to verify the Git commit
signature(s).</p>
</td>
</tr>
<tr>
@ -387,8 +391,9 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore).
If not provided, a default will be used, consult the documentation for your version to find out what those are.</p>
<p>Ignore overrides the set of excluded patterns in the .sourceignore format
(which is the same as .gitignore). If not provided, a default will be used,
consult the documentation for your version to find out what those are.</p>
</td>
</tr>
<tr>
@ -400,8 +405,8 @@ bool
</td>
<td>
<em>(Optional)</em>
<p>Suspend tells the controller to suspend the reconciliation of this source.
This flag tells the controller to suspend the reconciliation of this source.</p>
<p>Suspend tells the controller to suspend the reconciliation of this
GitRepository.</p>
</td>
</tr>
<tr>
@ -413,8 +418,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Determines which git client library to use.
Defaults to go-git, valid values are (&lsquo;go-git&rsquo;, &lsquo;libgit2&rsquo;).</p>
<p>GitImplementation specifies which Git client library implementation to
use. Defaults to &lsquo;go-git&rsquo;, valid values are (&lsquo;go-git&rsquo;, &lsquo;libgit2&rsquo;).</p>
</td>
</tr>
<tr>
@ -426,7 +431,8 @@ bool
</td>
<td>
<em>(Optional)</em>
<p>When enabled, after the clone is created, initializes all submodules within, using their default settings.
<p>RecurseSubmodules enables the initialization of all submodules within
the GitRepository as cloned from the URL, using their default settings.
This option is available only when using the &lsquo;go-git&rsquo; GitImplementation.</p>
</td>
</tr>
@ -440,8 +446,8 @@ This option is available only when using the &lsquo;go-git&rsquo; GitImplementat
</em>
</td>
<td>
<p>Include defines a list of GitRepository resources which artifacts should be included in the artifact produced for
this resource.</p>
<p>Include specifies a list of GitRepository resources which Artifacts
should be included in the Artifact produced for this GitRepository.</p>
</td>
</tr>
<tr>
@ -455,7 +461,8 @@ github.com/fluxcd/pkg/apis/acl.AccessFrom
</td>
<td>
<em>(Optional)</em>
<p>AccessFrom defines an Access Control List for allowing cross-namespace references to this object.</p>
<p>AccessFrom specifies an Access Control List for allowing cross-namespace
references to this object.</p>
</td>
</tr>
</table>
@ -1206,7 +1213,8 @@ github.com/fluxcd/pkg/apis/meta.ReconcileRequestStatus
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.GitRepositorySpec">GitRepositorySpec</a>)
</p>
<p>GitRepositoryInclude defines a source with a from and to path.</p>
<p>GitRepositoryInclude specifies a reference to a GitRepository which Artifact
(sub-)contents must be included, and where they should be placed.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -1227,7 +1235,8 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</em>
</td>
<td>
<p>Reference to a GitRepository to include.</p>
<p>GitRepositoryRef specifies the GitRepository which Artifact contents
must be included.</p>
</td>
</tr>
<tr>
@ -1239,7 +1248,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The path to copy contents from, defaults to the root directory.</p>
<p>FromPath specifies the path to copy contents from, defaults to the root
of the Artifact.</p>
</td>
</tr>
<tr>
@ -1251,7 +1261,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The path to copy contents to, defaults to the name of the source ref.</p>
<p>ToPath specifies the path to copy contents to, defaults to the name of
the GitRepositoryRef.</p>
</td>
</tr>
</tbody>
@ -1264,7 +1275,7 @@ string
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.GitRepositorySpec">GitRepositorySpec</a>)
</p>
<p>GitRepositoryRef defines the Git ref used for pull and checkout operations.</p>
<p>GitRepositoryRef specifies the Git reference to resolve and checkout.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -1284,7 +1295,9 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The Git branch to checkout, defaults to master.</p>
<p>Branch to checkout, defaults to &lsquo;master&rsquo; if no other field is defined.</p>
<p>When GitRepositorySpec.GitImplementation is set to &lsquo;go-git&rsquo;, a shallow
clone of the specified branch is performed.</p>
</td>
</tr>
<tr>
@ -1296,7 +1309,7 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The Git tag to checkout, takes precedence over Branch.</p>
<p>Tag to checkout, takes precedence over Branch.</p>
</td>
</tr>
<tr>
@ -1308,7 +1321,7 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The Git tag semver expression, takes precedence over Tag.</p>
<p>SemVer tag expression to checkout, takes precedence over Tag.</p>
</td>
</tr>
<tr>
@ -1320,7 +1333,10 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The Git commit SHA to checkout, if specified Tag filters will be ignored.</p>
<p>Commit SHA to checkout, takes precedence over all reference fields.</p>
<p>When GitRepositorySpec.GitImplementation is set to &lsquo;go-git&rsquo;, this can be
combined with Branch to shallow clone the branch, in which the commit is
expected to exist.</p>
</td>
</tr>
</tbody>
@ -1333,7 +1349,8 @@ string
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.GitRepository">GitRepository</a>)
</p>
<p>GitRepositorySpec defines the desired state of a Git repository.</p>
<p>GitRepositorySpec specifies the required configuration to produce an
Artifact for a Git repository.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -1352,7 +1369,7 @@ string
</em>
</td>
<td>
<p>The repository URL, can be a HTTP/S or SSH address.</p>
<p>URL specifies the Git repository URL, can be an HTTP/S or SSH address.</p>
</td>
</tr>
<tr>
@ -1366,9 +1383,12 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</td>
<td>
<em>(Optional)</em>
<p>The secret name containing the Git credentials.
For HTTPS repositories the secret must contain username and password fields.
For SSH repositories the secret must contain &lsquo;identity&rsquo;, &lsquo;identity.pub&rsquo; and &lsquo;known_hosts&rsquo; fields.</p>
<p>SecretRef specifies the Secret containing authentication credentials for
the GitRepository.
For HTTPS repositories the Secret must contain &lsquo;username&rsquo; and &lsquo;password&rsquo;
fields.
For SSH repositories the Secret must contain &lsquo;identity&rsquo;, &lsquo;identity.pub&rsquo;
and &lsquo;known_hosts&rsquo; fields.</p>
</td>
</tr>
<tr>
@ -1381,7 +1401,7 @@ Kubernetes meta/v1.Duration
</em>
</td>
<td>
<p>The interval at which to check for repository updates.</p>
<p>Interval at which to check the GitRepository for updates.</p>
</td>
</tr>
<tr>
@ -1395,7 +1415,7 @@ Kubernetes meta/v1.Duration
</td>
<td>
<em>(Optional)</em>
<p>The timeout for remote Git operations like cloning, defaults to 60s.</p>
<p>Timeout for Git operations like cloning, defaults to 60s.</p>
</td>
</tr>
<tr>
@ -1409,8 +1429,8 @@ GitRepositoryRef
</td>
<td>
<em>(Optional)</em>
<p>The Git reference to checkout and monitor for changes, defaults to
master branch.</p>
<p>Reference specifies the Git reference to resolve and monitor for
changes, defaults to the &lsquo;master&rsquo; branch.</p>
</td>
</tr>
<tr>
@ -1424,7 +1444,8 @@ GitRepositoryVerification
</td>
<td>
<em>(Optional)</em>
<p>Verification defines the configuration to verify the OpenPGP signature for the Git commit HEAD points to.</p>
<p>Verification specifies the configuration to verify the Git commit
signature(s).</p>
</td>
</tr>
<tr>
@ -1436,8 +1457,9 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore).
If not provided, a default will be used, consult the documentation for your version to find out what those are.</p>
<p>Ignore overrides the set of excluded patterns in the .sourceignore format
(which is the same as .gitignore). If not provided, a default will be used,
consult the documentation for your version to find out what those are.</p>
</td>
</tr>
<tr>
@ -1449,8 +1471,8 @@ bool
</td>
<td>
<em>(Optional)</em>
<p>Suspend tells the controller to suspend the reconciliation of this source.
This flag tells the controller to suspend the reconciliation of this source.</p>
<p>Suspend tells the controller to suspend the reconciliation of this
GitRepository.</p>
</td>
</tr>
<tr>
@ -1462,8 +1484,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Determines which git client library to use.
Defaults to go-git, valid values are (&lsquo;go-git&rsquo;, &lsquo;libgit2&rsquo;).</p>
<p>GitImplementation specifies which Git client library implementation to
use. Defaults to &lsquo;go-git&rsquo;, valid values are (&lsquo;go-git&rsquo;, &lsquo;libgit2&rsquo;).</p>
</td>
</tr>
<tr>
@ -1475,7 +1497,8 @@ bool
</td>
<td>
<em>(Optional)</em>
<p>When enabled, after the clone is created, initializes all submodules within, using their default settings.
<p>RecurseSubmodules enables the initialization of all submodules within
the GitRepository as cloned from the URL, using their default settings.
This option is available only when using the &lsquo;go-git&rsquo; GitImplementation.</p>
</td>
</tr>
@ -1489,8 +1512,8 @@ This option is available only when using the &lsquo;go-git&rsquo; GitImplementat
</em>
</td>
<td>
<p>Include defines a list of GitRepository resources which artifacts should be included in the artifact produced for
this resource.</p>
<p>Include specifies a list of GitRepository resources which Artifacts
should be included in the Artifact produced for this GitRepository.</p>
</td>
</tr>
<tr>
@ -1504,7 +1527,8 @@ github.com/fluxcd/pkg/apis/acl.AccessFrom
</td>
<td>
<em>(Optional)</em>
<p>AccessFrom defines an Access Control List for allowing cross-namespace references to this object.</p>
<p>AccessFrom specifies an Access Control List for allowing cross-namespace
references to this object.</p>
</td>
</tr>
</tbody>
@ -1517,7 +1541,7 @@ github.com/fluxcd/pkg/apis/acl.AccessFrom
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.GitRepository">GitRepository</a>)
</p>
<p>GitRepositoryStatus defines the observed state of a Git repository.</p>
<p>GitRepositoryStatus records the observed state of a Git repository.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -1537,7 +1561,8 @@ int64
</td>
<td>
<em>(Optional)</em>
<p>ObservedGeneration is the last observed generation.</p>
<p>ObservedGeneration is the last observed generation of the GitRepository
object.</p>
</td>
</tr>
<tr>
@ -1563,7 +1588,9 @@ string
</td>
<td>
<em>(Optional)</em>
<p>URL is the fetch link for the artifact output of the last repository sync.</p>
<p>URL is the dynamic fetch link for the latest Artifact.
It is provided on a &ldquo;best effort&rdquo; basis, and using the precise
GitRepositoryStatus.Artifact data is recommended.</p>
</td>
</tr>
<tr>
@ -1577,7 +1604,7 @@ Artifact
</td>
<td>
<em>(Optional)</em>
<p>Artifact represents the output of the last successful repository sync.</p>
<p>Artifact represents the last successful GitRepository reconciliation.</p>
</td>
</tr>
<tr>
@ -1591,7 +1618,8 @@ Artifact
</td>
<td>
<em>(Optional)</em>
<p>IncludedArtifacts represents the included artifacts from the last successful repository sync.</p>
<p>IncludedArtifacts contains a list of the last successfully included
Artifacts as instructed by GitRepositorySpec.Include.</p>
</td>
</tr>
<tr>
@ -1619,7 +1647,8 @@ github.com/fluxcd/pkg/apis/meta.ReconcileRequestStatus
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.GitRepositorySpec">GitRepositorySpec</a>)
</p>
<p>GitRepositoryVerification defines the OpenPGP signature verification process.</p>
<p>GitRepositoryVerification specifies the Git commit signature verification
strategy.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -1638,7 +1667,7 @@ string
</em>
</td>
<td>
<p>Mode describes what Git object should be verified, currently (&lsquo;head&rsquo;).</p>
<p>Mode specifies what Git object should be verified, currently (&lsquo;head&rsquo;).</p>
</td>
</tr>
<tr>
@ -1651,7 +1680,8 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</em>
</td>
<td>
<p>SecretRef containing the public keys of all trusted Git authors.</p>
<p>SecretRef specifies the Secret containing the public keys of trusted Git
authors.</p>
</td>
</tr>
</tbody>

View File

@ -5,7 +5,7 @@ This is the v1beta2 API specification for defining the desired state sources of
## Specification
* Source kinds:
+ GitRepository
+ [GitRepository](gitrepositories.md)
+ [HelmRepository](helmrepositories.md)
+ HelmChart
+ [Bucket](buckets.md)

View File

@ -0,0 +1,814 @@
# Git Repositories
The `GitRepository` API defines a Source to produce an Artifact for a Git
repository revision.
## Example
The following is an example of a GitRepository. It creates a tarball
(`.tar.gz`) Artifact with the fetched data from a Git repository for the
resolved reference.
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: podinfo
namespace: default
spec:
interval: 5m0s
url: https://github.com/stefanprodan/podinfo
ref:
branch: master
```
In the above example:
- A GitRepository named `podinfo` is created, indicated by the
`.metadata.name` field.
- The source-controller checks the Git repository every five minutes, indicated
by the `.spec.interval` field.
- It clones the `master` branch of the `https://github.com/stefanprodan/podinfo`
repository, indicated by the `.spec.ref.branch` and `.spec.url` fields.
- The specified branch and resolved HEAD revision are used as the Artifact
revision, reported in-cluster in the `.status.artifact.revision` field.
- When the current GitRepository revision differs from the latest fetched
revision, a new Artifact is archived.
- The new Artifact is reported in the `.status.artifact` field.
You can run this example by saving the manifest into `gitrepository.yaml`.
1. Apply the resource on the cluster:
```sh
kubectl apply -f gitrepository.yaml
```
2. Run `kubectl get gitrepository` to see the GitRepository:
```console
NAME URL READY STATUS AGE
podinfo https://github.com/stefanprodan/podinfo True stored artifact for revision 'master/132f4e719209eb10b9485302f8593fc0e680f4fc' 5s
```
3. Run `kubectl describe gitrepository podinfo` to see the [Artifact](#artifact)
and [Conditions](#conditions) in the GitRepository's Status:
```console
...
Status:
Artifact:
Checksum: 95e386f421272710c4cedbbd8607dbbaa019d500e7a5a0b6720bc7bebefc7bf2
Last Update Time: 2022-02-14T11:23:36Z
Path: gitrepository/default/podinfo/132f4e719209eb10b9485302f8593fc0e680f4fc.tar.gz
Revision: master/132f4e719209eb10b9485302f8593fc0e680f4fc
URL: http://source-controller.source-system.svc.cluster.local./gitrepository/default/podinfo/132f4e719209eb10b9485302f8593fc0e680f4fc.tar.gz
Conditions:
Last Transition Time: 2022-02-14T11:23:36Z
Message: stored artifact for revision 'master/132f4e719209eb10b9485302f8593fc0e680f4fc'
Observed Generation: 1
Reason: Succeeded
Status: True
Type: Ready
Observed Generation: 1
URL: http://source-controller.source-system.svc.cluster.local./gitrepository/default/podinfo/latest.tar.gz
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal GitOperationSucceed 62s source-controller cloned 'https://github.com/stefanprodan/podinfo' and checked out revision 'master/132f4e719209eb10b9485302f8593fc0e680f4fc'
Normal NewArtifact 62s source-controller stored artifact for revision 'master/132f4e719209eb10b9485302f8593fc0e680f4fc'
```
## Writing a GitRepository spec
As with all other Kubernetes config, a GitRepository needs `apiVersion`,
`kind`, and `metadata` fields. The name of a GitRepository object must be a
valid [DNS subdomain name](https://kubernetes.io/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
A GitRepository also needs a
[`.spec` section](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
### URL
`.spec.url` is a required field that specifies the HTTP/S or SSH address of the
Git repository.
**Note:** Unlike using `git`, the
[shorter scp-like syntax](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols#_the_ssh_protocol)
is not supported for SSH addresses (e.g. `user@example.com:repository.git`).
Instead, the valid URL format is `ssh://user@example.com:22/repository.git`.
### Secret reference
`.spec.secretRef.name` is an optional field to specify a name reference to a
Secret in the same namespace as the GitRepository, containing authentication
credentials for the Git repository.
The required fields in the Secret depend on the specified protocol in the
[URL](#url).
#### Basic access authentication
To authenticate towards a Git repository over HTTPS using basic access
authentication (in other words: using a username and password), the referenced
Secret is expected to contain `.data.username` and `.data.password` values.
```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: basic-access-auth
type: Opaque
data:
username: <BASE64>
password: <BASE64>
```
#### HTTPS Certificate Authority
To provide a Certificate Authority to trust while connecting with a Git
repository over HTTPS, the referenced Secret can contain a `.data.caFile`
value.
```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: https-ca-credentials
namespace: default
type: Opaque
data:
caFile: <BASE64>
```
#### SSH authentication
To authenticate towards a Git repository over SSH, the referenced Secret is
expected to contain `.data.identity`, `.data.identity.pub` and `known_hosts`
fields. With the respective private and public key of the SSH key pair, and the
host keys of the Git repository.
```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: ssh-credentials
type: Opaque
data:
identity: <BASE64>
identity.pub: <BASE64>
known_hosts: <BASE64>
```
### Interval
`.spec.interval` is a required field that specifies the interval at which the
Git repository must be fetched.
After successfully reconciling the object, the source-controller requeues it
for inspection after the specified interval. The value must be in a
[Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
e.g. `10m0s` to reconcile the object every 10 minutes.
If the `.metadata.generation` of a resource changes (due to e.g. a change to
the spec), this is handled instantly outside the interval window.
### Timeout
`.spec.timeout` is an optional field to specify a timeout for Git operations
like cloning. The value must be in a
[Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
e.g. `1m30s` for a timeout of one minute and thirty seconds. The default value
is `60s`.
### Reference
`.spec.ref` is an optional field to specify the Git reference to resolve and
watch for changes. References are specified in one or more subfields
(`.branch`, `.tag`, `.semver`, `.commit`), with latter listed fields taking
precedence over earlier ones. If not specified, it defaults to a `master`
branch reference.
#### Branch example
To Git checkout a specified branch, use `.spec.ref.branch`:
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
ref:
branch: <branch-name>
```
Using the [`go-git` Git implementation](#git-implementation), this will perform
a shallow clone to only fetch the specified branch.
#### Tag example
To Git checkout a specified tag, use `.spec.ref.tag`:
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
ref:
tag: <tag-name>
```
This field takes precedence over [`.branch`](#branch-example).
#### SemVer example
To Git checkout a tag based on a
[SemVer range](https://github.com/Masterminds/semver#checking-version-constraints),
use `.spec.ref.semver`:
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
ref:
# SemVer range reference: https://github.com/Masterminds/semver#checking-version-constraints
semver: "<semver-range>"
```
This field takes precedence over [`.branch`](#branch-example) and
[`.tag`](#tag-example).
#### Commit example
To Git checkout a specified commit, use `.spec.ref.commit`:
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
ref:
commit: "<commit SHA>"
```
This field takes precedence over all other fields. Using the [`go-git` Git
implementation](#git-implementation), it can be combined with `.spec.ref.branch`
to perform a shallow clone of the branch, in which the commit must exist:
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
ref:
branch: <branch>
commit: "<commit SHA within branch>"
```
### Verification
`.spec.verify` is an optional field to enable the verification of Git commit
signatures. The field offers two subfields:
- `.mode`, to specify what Git commit object should be verified. Only supports
`head` at present.
- `.secretRef.name`, to specify a reference to a Secret in the same namespace as
the GitRepository. Containing the (PGP) public keys of trusted Git authors.
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
name: podinfo
namespace: default
spec:
interval: 1m
url: https://github.com/stefanprodan/podinfo
ref:
branch: master
verify:
mode: head
secretRef:
name: pgp-public-keys
```
When the verification succeeds, the controller adds a Condition with the
following attributes to the GitRepository's `.status.conditions`:
- `type: SourceVerifiedCondition`
- `status: "True"`
- `reason: Succeeded`
#### Verification Secret example
```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: pgp-public-keys
namespace: default
type: Opaque
data:
author1.asc: <BASE64>
author2.asc: <BASE64>
```
Exporting armored public keys (`.asc` files) using `gpg`, and generating a
Secret:
```sh
# Export armored public keys
gpg --export --armor 3CB12BA185C47B67 > author1.asc
gpg --export --armor 6A7436E8790F8689 > author2.asc
# Generate secret
kubectl create secret generic pgp-public-keys \
--from-file=author1.asc \
--from-file=author2.asc \
-o yaml
```
### Ignore
`.spec.ignore` is an optional field to specify rules in [the `.gitignore`
pattern format](https://git-scm.com/docs/gitignore#_pattern_format). Paths
matching the defined rules are excluded while archiving.
When specified, `.spec.ignore` overrides the [default exclusion
list](#default-exclusions), and may overrule the [`.sourceignore` file
exclusions](#sourceignore-file). See [excluding files](#excluding-files)
for more information.
### Suspend
`.spec.suspend` is an optional field to suspend the reconciliation of a
GitRepository. When set to `true`, the controller will stop reconciling the
GitRepository, and changes to the resource or in the Git repository will not
result in a new Artifact. When the field is set to `false` or removed, it will
resume.
### Git implementation
`.spec.gitImplementation` is an optional field to change the client library
implementation used for Git operations (e.g. clone, checkout). The default
value is `go-git`.
Unless you need support for a specific Git wire protocol functionality not
supported by the default implementation (as documented below), changing the
implementation is generally not recommended as it can come with its own set of
drawbacks. For example, not being able to make use of shallow clones forces the
controller to fetch the whole Git history tree instead of a specific one,
resulting in an increase of disk space and traffic usage.
| Git Implementation | Shallow Clones | Git Submodules | V2 Protocol Support |
|--------------------|----------------|----------------|---------------------|
| `go-git` | true | true | false |
| `libgit2` | false | false | true |
Some Git providers like Azure DevOps _require_ the `libgit2` implementation, as
their Git servers provide only support for the
[v2 protocol](https://git-scm.com/docs/protocol-v2).
#### Proxy support
When a proxy is configured in the source-controller Pod through the appropriate
environment variables, for example `HTTPS_PROXY`, `NO_PROXY`, etc. There may be
some limitations in the proxy support based on the Git implementation.
| Git Implementation | HTTP_PROXY | HTTPS_PROXY | NO_PROXY | Self-signed Certs |
|--------------------|------------|-------------|----------|-------------------|
| `go-git` | true | true | true | false |n
| `libgit2` | false | true | true | true |
### Recurse submodules
`.spec.recurseSubmodules` is an optional field to enable the initialization of
all submodules within the cloned Git repository, using their default settings.
This option is only available when using the (default) `go-git` [Git
implementation](#git-implementation), and defaults to `false`.
Note that for most Git providers (e.g. GitHub and GitLab), deploy keys can not
be used as reusing a key across multiple repositories is not allowed. You have
to use either [HTTPS token-based authentication](#basic-access-authentication),
or an SSH key belonging to a (bot) user who has access to the main repository
and all submodules.
### Include
`.spec.include` is an optional field to map the contents of GitRepository
Artifacts into another. This may look identical to Git submodules but has
multiple benefits over regular submodules:
- Including a `GitRepository` allows you to use different authentication
methods for different repositories.
- A change in the included repository will trigger an update of the including
repository.
- Multiple `GitRepository` objects could include the same repository, which
decreases the amount of cloning done compared to using submodules.
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: include-example
spec:
include:
- repository:
name: other-repository
fromPath: deploy/kubernetes
toPath: base/app
```
The `.fromPath` and `.toPath` fields allow you to limit the files included, and
where they will be copied to. If you do not specify a value for `.fromPath`,
all files from the referenced GitRepository Artifact will be included. The
`.toPath` defaults to the `.repository.name` (e.g. `./other-repository/*`).
## Working with GitRepositories
### Excluding files
By default, files which match the [default exclusion rules](#default-exclusions)
are excluded while archiving the Git repository contents as an Artifact. It is
possible to overwrite and/or overrule the default exclusions using a file in
the Git repository and/or an in-spec set of rules.
#### `.sourceignore` file
Excluding files is possible by adding a `.sourceignore` file in the Git
repository. The `.sourceignore` file follows [the `.gitignore` pattern
format](https://git-scm.com/docs/gitignore#_pattern_format), and
pattern entries may overrule [default exclusions](#default-exclusions).
#### Ignore spec
Another option is to define the exclusions within the GitRepository spec, using
the [`.spec.ignore` field](#ignore). Specified rules override the [default
exclusion list](#default-exclusions), and may overrule `.sourceignore` file
exclusions.
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
ignore: |
# exclude all
/*
# include deploy dir
!/deploy
# exclude file extensions from deploy dir
/deploy/**/*.md
/deploy/**/*.txt
```
### Triggering a reconcile
To manually tell the source-controller to reconcile a GitRepository outside the
[specified interval window](#interval), a GitRepository can be annotated with
`reconcile.fluxcd.io/requestedAt: <arbitrary value>`. Annotating the resource
queues the GitRepository for reconciliation if the `<arbitrary-value>` differs
from the last value the controller acted on, as reported in
[`.status.lastHandledReconcileAt`](#last-handled-reconcile-at).
Using `kubectl`:
```sh
kubectl annotate --overwrite gitrepository/<repository-name> reconcile.fluxcd.io/requestedAt="$(date +%s)"
```
Using `flux`:
```sh
flux reconcile source git <repository-name>
```
### Waiting for `Ready`
When a change is applied, it is possible to wait for the GitRepository to reach
a [ready state](#ready-gitrepository) using `kubectl`:
```sh
kubectl wait gitrepository/<repository-name> --for=condition=ready --timeout=1m
```
### Suspending and resuming
When you find yourself in a situation where you temporarily want to pause the
reconciliation of a GitRepository, you can suspend it using the
[`.spec.suspend` field](#suspend).
#### Suspend a GitRepository
In your YAML declaration:
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
suspend: true
```
Using `kubectl`:
```sh
kubectl patch gitrepository <repository-name> -p '{\"spec\": {\"suspend\" : true }}'
```
Using `flux`:
```sh
flux suspend source git <repository-name>
```
**Note:** When a GitRepository has an Artifact and is suspended, and this
Artifact later disappears from the storage due to e.g. the source-controller
Pod being evicted from a Node, this will not be reflected in the
GitRepository's Status until it is resumed.
#### Resume a GitRepository
In your YAML declaration, comment out (or remove) the field:
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
spec:
# suspend: true
```
**Note:** Setting the field value to `false` has the same effect as removing
it, but does not allow for "hot patching" using e.g. `kubectl` while practicing
GitOps; as the manually applied patch would be overwritten by the declared
state in Git.
Using `kubectl`:
```sh
kubectl patch gitrepository <repository-name> -p '{\"spec\" : {\"suspend\" : false }}'
```
Using `flux`:
```sh
flux resume source git <repository-name>
```
### Debugging a GitRepository
There are several ways to gather information about a GitRepository for
debugging purposes.
#### Describe the GitRepository
Describing a GitRepository using
`kubectl describe gitrepository <repository-name>`
displays the latest recorded information for the resource in the `Status` and
`Events` sections:
```console
...
Status:
...
Conditions:
Last Transition Time: 2022-02-14T09:40:27Z
Message: reconciling new generation 2
Observed Generation: 2
Reason: NewGeneration
Status: True
Type: Reconciling
Last Transition Time: 2022-02-14T09:40:27Z
Message: failed to checkout and determine revision: unable to clone 'https://github.com/stefanprodan/podinfo': couldn't find remote ref "refs/heads/invalid"
Observed Generation: 2
Reason: GitOperationFailed
Status: False
Type: Ready
Last Transition Time: 2022-02-14T09:40:27Z
Message: failed to checkout and determine revision: unable to clone 'https://github.com/stefanprodan/podinfo': couldn't find remote ref "refs/heads/invalid"
Observed Generation: 2
Reason: GitOperationFailed
Status: True
Type: FetchFailed
Observed Generation: 1
URL: http://source-controller.source-system.svc.cluster.local./gitrepository/default/gitrepository-sample/latest.tar.gz
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning GitOperationFailed 2s (x9 over 4s) source-controller failed to checkout and determine revision: unable to clone 'https://github.com/stefanprodan/podinfo': couldn't find remote ref "refs/heads/invalid"
```
#### Trace emitted Events
To view events for specific GitRepository(s), `kubectl get events` can be used
in combination with `--field-sector` to list the Events for specific objects.
For example, running
```sh
kubectl get events --field-selector involvedObject.kind=GitRepository,involvedObject.name=<repository-name>
```
lists
```console
LAST SEEN TYPE REASON OBJECT MESSAGE
2m14s Normal GitOperationSucceed gitrepository/<repository-name> cloned 'https://github.com/stefanprodan/podinfo' and checked out revision 'master/132f4e719209eb10b9485302f8593fc0e680f4fc'
2m14s Normal NewArtifact gitrepository/<repository-name> stored artifact for revision 'master/132f4e719209eb10b9485302f8593fc0e680f4fc'
94s Warning GitOperationFailed gitrepository/gitrepository-sample failed to checkout and determine revision: unable to clone 'https://github.com/stefanprodan/podinfo': couldn't find remote ref "refs/heads/invalid"
```
Besides being reported in Events, the reconciliation errors are also logged by
the controller. The Flux CLI offer commands for filtering the logs for a
specific GitRepository, e.g.
`flux logs --level=error --kind=GitRepository --name=<repository-name>`.
## GitRepository Status
### Artifact
The GitRepository reports the latest synchronized state from the Git repository
as an Artifact object in the `.status.artifact` of the resource.
The Artifact file is a gzip compressed TAR archive (`<commit sha>.tar.gz`), and
can be retrieved in-cluster from the `.status.artifact.url` HTTP address.
#### Artifact example
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: <repository-name>
status:
artifact:
checksum: e750c7a46724acaef8f8aa926259af30bbd9face2ae065ae8896ba5ee5ab832b
lastUpdateTime: "2022-01-29T06:59:23Z"
path: gitrepository/<namespace>/<repository-name>/c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2.tar.gz
revision: master/363a6a8fe6a7f13e05d34c163b0ef02a777da20a
url: http://source-controller.<namespace>.svc.cluster.local./gitrepository/<namespace>/<repository-name>/363a6a8fe6a7f13e05d34c163b0ef02a777da20a.tar.gz
```
#### Default exclusions
The following files and extensions are excluded from the Artifact by
default:
- Git files (`.git/, .gitignore, .gitmodules, .gitattributes`)
- File extensions (`.jpg, .jpeg, .gif, .png, .wmv, .flv, .tar.gz, .zip`)
- CI configs (`.github/, .circleci/, .travis.yml, .gitlab-ci.yml, appveyor.yml, .drone.yml, cloudbuild.yaml, codeship-services.yml, codeship-steps.yml`)
- CLI configs (`.goreleaser.yml, .sops.yaml`)
- Flux v1 config (`.flux.yaml`)
To define your own exclusion rules, see [excluding files](#excluding-files).
### Conditions
A GitRepository enters various states during its lifecycle, reflected as
[Kubernetes Conditions][typical-status-properties].
It can be [reconciling](#reconciling-gitrepository) while fetching the Git
state, it can be [ready](#ready-gitrepository), or it can [fail during
reconciliation](#failed-gitrepository).
The GitRepository API is compatible with the [kstatus specification][kstatus-spec],
and reports `Reconciling` and `Stalled` conditions where applicable to
provide better (timeout) support to solutions polling the GitRepository to
become `Ready`.
#### Reconciling GitRepository
The source-controller marks a GitRepository as _reconciling_ when one of the
following is true:
- There is no current Artifact for the GitRepository, or the reported Artifact
is determined to have disappeared from the storage.
- The generation of the GitRepository is newer than the [Observed
Generation](#observed-generation).
- The newly resolved Artifact revision differs from the current Artifact.
When the GitRepository is "reconciling", the `Ready` Condition status becomes
`False`, and the controller adds a Condition with the following attributes to
the GitRepository's `.status.conditions`:
- `type: Reconciling`
- `status: "True"`
- `reason: NewGeneration` | `reason: NoArtifact` | `reason: NewRevision`
If the reconciling state is due to a new revision, an additional Condition is
added with the following attributes:
- `type: ArtifactOutdated`
- `status: "True"`
- `reason: NewRevision`
Both Conditions have a ["negative polarity"][typical-status-properties],
and are only present on the GitRepository while their status value is `"True"`.
#### Ready GitRepository
The source-controller marks a GitRepository as _ready_ when it has the
following characteristics:
- The GitRepository reports an [Artifact](#artifact).
- The reported Artifact exists in the controller's Artifact storage.
- The controller was able to communicate with the remote Git repository using
the current spec.
- The revision of the reported Artifact is up-to-date with the latest
resolved revision of the remote Git repository.
When the GitRepository is "ready", the controller sets a Condition with the
following attributes in the GitRepository's `.status.conditions`:
- `type: Ready`
- `status: "True"`
- `reason: Succeeded`
This `Ready` Condition will retain a status value of `"True"` until the
GitRepository is marked as [reconciling](#reconciling-gitrepository), or e.g. a
[transient error](#failed-gitrepository) occurs due to a temporary network issue.
#### Failed GitRepository
The source-controller may get stuck trying to produce an Artifact for a
GitRepository without completing. This can occur due to some of the following
factors:
- The remote Git repository [URL](#url) is temporarily unavailable.
- The Git repository does not exist.
- The [Secret reference](#secret-reference) contains a reference to a
non-existing Secret.
- A specified Include is unavailable.
- The verification of the Git commit signature failed.
- The credentials in the referenced Secret are invalid.
- The GitRepository spec contains a generic misconfiguration.
When this happens, the controller sets the `Ready` Condition status to `False`,
and adds a Condition with the following attributes to the GitRepository's
`.status.conditions`:
- `type: FetchFailed` | `type: IncludeUnavailableCondition`
- `status: "True"`
- `reason: AuthenticationFailed` | `reason: GitOperationFailed` | `reason: StorageOperationFailed`
This condition has a ["negative polarity"][typical-status-properties],
and is only present on the GitRepository while the status value is `"True"`.
In addition to the above Condition types, when the
[verification of a Git commit signature](#verification) fails. A condition with
the following attributes is added to the GitRepository's `.status.conditions`:
- `type: SourceVerifiedCondition`
- `status: "False"`
- `reason: Failed`
While the GitRepository has one or more of these Conditions, the controller
will continue to attempt to produce an Artifact for the resource with an
exponential backoff, until it succeeds and the GitRepository is marked as
[ready](#ready-gitrepository).
Note that a GitRepository can be [reconciling](#reconciling-gitrepository)
while failing at the same time, for example due to a newly introduced
configuration issue in the GitRepository spec.
### Observed Generation
The source-controller reports an [observed generation][typical-status-properties]
in the GitRepository's `.status.observedGeneration`. The observed generation is
the latest `.metadata.generation` which resulted in either a [ready state](#ready-gitrepository),
or stalled due to error it can not recover from without human
intervention.
### Last Handled Reconcile At
The source-controller reports the last `reconcile.fluxcd.io/requestedAt`
annotation value it acted on in the `.status.lastHandledReconcileAt` field.
For practical information about this field, see [triggering a
reconcile](#triggering-a-reconcile).
[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
[kstatus-spec]: https://github.com/kubernetes-sigs/cli-utils/tree/master/pkg/kstatus