Documentation ¶
Overview ¶
Package changes implements Go module version management for a multi-module git repository.
Repository ¶
The Repository struct is a representation of a git repository containing multiple Go modules. Repository handles the whole release process with respect to versioning, including tagging the git repository and updating CHANGELOG, version.go, and go.mod files. The sequence of steps required to create a release of the SDK can be run from the Repository's DoRelease function:
repo, err := changes.NewRepository("path/to/repository") if err != nil { panic(err) } repo.DoRelease("2020-08-12")
After this code snippet runs, the versions of modules within the specified repository will be updated based on change metadata contained in the repository.
Metadata ¶
In order to make module versioning decisions during a release, the Repository's DoRelease function consumes metadata about changes included in the release. The metadata is stored in the root of the repository in a .changes directory. The Metadata struct provides a way to load, create, and modify the metadata in the .changes directory. The .changes directory is structured as follows:
.changes/ next-release/ contains Change metadata for pending changes (to be included in the next release). releases/ contains Release metadata for previous releases. versions.json is a VersionEnclosure representing the state of the repository at the last release.
There are three file formats used in the .changes directory corresponding to three structs: Change, Release, and VersionEnclosure.
Changelogs ¶
The Repository's DoRelease function pdates both a top level CHANGELOG.md and per-module CHANGELOG.md files. The CHANGELOG.md in the root of the repository provides a consolidated view of all changelog entries for every module. This means that the root module does not have its own CHANGELOG.
The Release struct handles the rendering of CHANGELOG files, generating an entry that is prepended to CHANGELOG files during a release.
Dependencies within the SDK ¶
As part of the Repository's release process, any module within the repository that depends upon another module in the repository will have its dependency updated to the latest version. So, after a release all modules in the SDK depend on the latest version of any other SDK module.
Index ¶
- Constants
- func AffectedModules(changes []Change) []string
- func ChangeToTemplate(change Change) ([]byte, error)
- func GetChangesPath() (string, error)
- func GetCurrentModule() (string, error)
- func MatchWildcardModules(modules []string, wildcard string) ([]string, error)
- func ModIsWildcard(mod string) bool
- type Change
- type ChangeType
- func (c ChangeType) ChangelogPrefix() string
- func (c *ChangeType) Set(s string) error
- func (c ChangeType) String() string
- func (c *ChangeType) UnmarshalJSON(data []byte) error
- func (c *ChangeType) UnmarshalYAML(unmarshal func(interface{}) error) error
- func (c ChangeType) VersionIncrement() VersionIncrement
- type Metadata
- func (m *Metadata) AddChange(c Change) error
- func (m *Metadata) AddChanges(changes []Change) error
- func (m *Metadata) AddChangesFromTemplate(template []byte) ([]Change, error)
- func (m *Metadata) ClearChanges() error
- func (m *Metadata) CreateRelease(id string, bumps map[string]VersionBump, dryRun bool) (*Release, error)
- func (m *Metadata) GetChangeByID(id string) (Change, error)
- func (m *Metadata) GetChanges(module string) []Change
- func (m *Metadata) RemoveChangeByID(id string) error
- func (m *Metadata) SaveChange(c Change) error
- func (m *Metadata) SaveEnclosure(enc VersionEnclosure) error
- func (m *Metadata) UpdateChangeFromTemplate(oldChange Change, template []byte) ([]Change, error)
- type ModuleGraph
- type Release
- func (r *Release) AffectedModules() []string
- func (r *Release) AnnouncementsSection() ([]string, error)
- func (r *Release) CoreSection() ([]string, error)
- func (r *Release) RenderChangelog() (string, error)
- func (r *Release) RenderChangelogForModule(module string, topLevel bool) (string, error)
- func (r *Release) ServiceSection() ([]string, error)
- type Repository
- func (r *Repository) DiscoverVersions(selector VersionSelector) (VersionEnclosure, map[string]VersionBump, error)
- func (r *Repository) DoRelease(releaseID string, push, interactive bool) error
- func (r *Repository) InitializeVersions() error
- func (r *Repository) ModuleHashes(enc VersionEnclosure) (map[string]string, error)
- func (r *Repository) Modules() ([]string, error)
- func (r *Repository) Tidy() error
- func (r *Repository) UpdateAllChangelogs(release *Release, pending bool) error
- func (r *Repository) UpdateChangelog(release *Release, pending bool) error
- func (r *Repository) UpdateModuleChangelog(release *Release, module string, pending bool) error
- func (r *Repository) UpdateVersionFiles(enc VersionEnclosure) error
- type Version
- type VersionBump
- type VersionEnclosure
- type VersionIncrement
- type VersionSelector
Constants ¶
const SchemaVersion = 1
SchemaVersion defines the current JSON schema version for persistent data types (Change, Release, ...)
Variables ¶
This section is empty.
Functions ¶
func AffectedModules ¶
AffectedModules returns a sorted list of all modules affected by the given Changes. A module is considered affected if it is the Module of one or more Changes that will result in a version increment.
func ChangeToTemplate ¶
ChangeToTemplate returns a Change template populated with the given Change's data.
func GetChangesPath ¶
GetChangesPath searches upward from the current directory for a .changes directory, returning a relative path from the current directory to the .changes directory.
func GetCurrentModule ¶
GetCurrentModule returns a shortened module path (from the root of the repository to the module, not a full import path) for the Go module containing the current directory.
func MatchWildcardModules ¶
MatchWildcardModules filters modules, returning only the modules that match the given wildcard.
func ModIsWildcard ¶
ModIsWildcard returns whether the given module ends in the wildcard pattern.
Types ¶
type Change ¶
type Change struct { ID string // ID is a unique identifier for this Change. SchemaVersion int // SchemaVersion is the version of the library's types used to create this Change. Module string // Module is a shortened Go module path for the module affected by this Change. Module is the path from the root of the repository to the module. Type ChangeType // Type indicates what category of Change was made. Type may be either "feature" or "bugfix". Description string // Description is a human readable description of this Change meant to be included in a CHANGELOG. MinVersion string // MinVersion is a semver tag that the module should be minimally bumped to. // AffectedModules is a list of modules affected by this Change. AffectedModules is only non-nil when the Change's // Module has a wildcard, in which case AffectedModules contains all modules matching the wildcard Module that the // Change affects. AffectedModules []string }
Change represents a change to a single Go module.
func NewChanges ¶
func NewChanges(modules []string, changeType ChangeType, description string, minVersion string) ([]Change, error)
NewChanges returns a Change slice containing a Change with the given type and description for each of the specified modules.
func NewWildcardChange ¶
func NewWildcardChange(modulePath string, changeType ChangeType, description string, affectedModules []string, minVersion string) (Change, error)
NewWildcardChange creates a wildcard Change.
func TemplateToChanges ¶
TemplateToChanges parses the provided filledTemplate into the provided Change. If Change has no ID, TemplateToChange will set the ID.
func (Change) IndentedDescription ¶
IndentedDescription returns the Change's Description with each line except for the first prefixed with the given string.
type ChangeType ¶
type ChangeType string
ChangeType describes the type of change made to a Go module.
const ( // FeatureChangeType is a constant change type for a new feature. FeatureChangeType ChangeType = "feature" // BugFixChangeType is a constant change type for a bug fix. BugFixChangeType ChangeType = "bugfix" // MajorChangeType is a constant change type for a major version updates (from v0 => v1). MajorChangeType ChangeType = "major" // DependencyChangeType is a constant change type for a dependency update. DependencyChangeType ChangeType = "dependency" // AnnouncementChangeType is a constant change type for an SDK announcement. AnnouncementChangeType ChangeType = "announcement" // DocumentationChangeType is a constant change type for an SDK announcement. DocumentationChangeType ChangeType = "documentation" )
func ParseChangeType ¶
func ParseChangeType(v string) (ChangeType, error)
ParseChangeType attempts to parse the given string v into a ChangeType, returning an error if the string is invalid.
func (ChangeType) ChangelogPrefix ¶
func (c ChangeType) ChangelogPrefix() string
ChangelogPrefix returns the CHANGELOG header the ChangeType should be grouped under.
func (*ChangeType) Set ¶
func (c *ChangeType) Set(s string) error
Set parses the given string and correspondingly sets the ChangeType, returning an error if the string could not be parsed.
func (ChangeType) String ¶
func (c ChangeType) String() string
String returns a string representation of the ChangeType
func (*ChangeType) UnmarshalJSON ¶
func (c *ChangeType) UnmarshalJSON(data []byte) error
UnmarshalJSON implements the encoding/json package's Unmarshaler interface, additionally providing change type validation.
func (*ChangeType) UnmarshalYAML ¶
func (c *ChangeType) UnmarshalYAML(unmarshal func(interface{}) error) error
UnmarshalYAML implements yaml.v2's Unmarshaler interface, additionally providing change type validation.
func (ChangeType) VersionIncrement ¶
func (c ChangeType) VersionIncrement() VersionIncrement
VersionIncrement returns the VersionIncrement corresponding to the given ChangeType.
type Metadata ¶
type Metadata struct { ChangePath string // ChangePath is the relative path from the current directory to .changes Changes []Change // Changes holds all pending change metadata in the .changes/next-release directory Releases []*Release // Releases contains all releases in the .changes/releases directory CurrentVersions VersionEnclosure // CurrentVersions is the .changes/versions.json enclosure of current module versions }
Metadata is a representation of the change metadata stored in a .changes directory.
func LoadMetadata ¶
LoadMetadata loads the .changes directory at the given path.
func (*Metadata) AddChange ¶
AddChange adds the given Change to the Metadata's Changes and saves the Change to the next-release directory.
func (*Metadata) AddChanges ¶
AddChanges adds the given Changes to Metadata's Changes and saves the Changes to the next-release directory.
func (*Metadata) AddChangesFromTemplate ¶
AddChangesFromTemplate parses the given YAML template, adding the resulting Changes to Metadata's Changes and saving the Changes to the next-release directory. AddChangesFromTemplate returns the created Changes.
func (*Metadata) ClearChanges ¶
ClearChanges removes all Changes from the Metadata's Changes and deletes the Change files in the .changes/next-release directory.
func (*Metadata) CreateRelease ¶
func (m *Metadata) CreateRelease(id string, bumps map[string]VersionBump, dryRun bool) (*Release, error)
CreateRelease consolidates the Metadata's pending Changes into a Release. This operation will remove all Changes from the Metadata and delete change files in .changes/next-release. A release file will also be created in .changes/releases. If dryRun is true, CreateRelease will return a Release, but not modify change or release files.
func (*Metadata) GetChangeByID ¶
GetChangeByID returns the pending Change with the given id.
func (*Metadata) GetChanges ¶
GetChanges returns all pending Changes with a module matching the given module. If module is empty, returns all Changes.
func (*Metadata) RemoveChangeByID ¶
RemoveChangeByID removes the Change with the specified id from the Metadata's Changes and also removes the Change from the .changes/next-release directory.
func (*Metadata) SaveChange ¶
SaveChange saves the given change to the .changes/next-release directory.
func (*Metadata) SaveEnclosure ¶
func (m *Metadata) SaveEnclosure(enc VersionEnclosure) error
SaveEnclosure updates the Metadata's enclosure and updates the versions.json file.
type ModuleGraph ¶
ModuleGraph is a mapping between modules in a repository and a list of modules within the same repository that depend on that module.
type Release ¶
type Release struct { ID string SchemaVersion int VersionBumps map[string]VersionBump Changes []Change }
Release represents a single SDK release, which contains all change metadata and their resulting version bumps.
func (*Release) AffectedModules ¶
AffectedModules returns a sorted list of all modules affected by this Release. A module is considered affected if it is the Module of one or more Changes in the Release.
func (*Release) AnnouncementsSection ¶
AnnouncementsSection returns a list of Changelog bullet entries that should be included under the Announcements header.
func (*Release) CoreSection ¶
CoreSection returns a list of Changelog bullet entries that should be included under the Core SDK header.
func (*Release) RenderChangelog ¶
RenderChangelog generates a top level CHANGELOG.md for the Release r.
func (*Release) RenderChangelogForModule ¶
RenderChangelogForModule returns a new markdown section of a module's CHANGELOG based on the Changes in the Release.
func (*Release) ServiceSection ¶
ServiceSection returns a list of Changelog bullet entries that should be included under the Service Clients header.
type Repository ¶
type Repository struct { RootPath string // RootPath is the path to the root of the repository. Metadata *Metadata // Metadata is the repository's .changes metadata. // Logf is a logging function. If nil, Repository will not log anything. Logf func(string, ...interface{}) // contains filtered or unexported fields }
Repository is a representation of a git repository containing multiple Go modules.
func NewRepository ¶
func NewRepository(path string) (*Repository, error)
NewRepository loads the repository at the given path.
func (*Repository) DiscoverVersions ¶
func (r *Repository) DiscoverVersions(selector VersionSelector) (VersionEnclosure, map[string]VersionBump, error)
DiscoverVersions creates a VersionEnclosure containing all Go modules in the Repository. The version of each module is determined by the provided VersionSelector.
func (*Repository) DoRelease ¶
func (r *Repository) DoRelease(releaseID string, push, interactive bool) error
DoRelease runs the automated release process, consuming the given Repository's Metadata, updating module's go.mod files, creating a release JSON file, committing changes, tagging the repository, and pushing.
func (*Repository) InitializeVersions ¶
func (r *Repository) InitializeVersions() error
InitializeVersions creates an initial versions.json enclosure in the Repository's .changes directory. The VersionEnclosure created by InitializeVersions will include all modules that have a tagged version in git and their corresponding versions.
func (*Repository) ModuleHashes ¶
func (r *Repository) ModuleHashes(enc VersionEnclosure) (map[string]string, error)
ModuleHashes computes and returns a mapping between shortened module names and their corresponding Go module checksum. Since the version of a module is used to compute the Go checksum (i.e. two modules with the same directory contents have a different checksum if their versions are different), the versions of the given VersionEnclosure will be used for this purpose.
func (*Repository) Modules ¶
func (r *Repository) Modules() ([]string, error)
Modules returns all Go modules under the given Repository. The list of module names returns are shortened to be relative to the root of the repository.
func (*Repository) Tidy ¶
func (r *Repository) Tidy() error
Tidy runs go mod tidy on all modules in the repository.
func (*Repository) UpdateAllChangelogs ¶
func (r *Repository) UpdateAllChangelogs(release *Release, pending bool) error
UpdateAllChangelogs generates changelog entries for both the top level CHANGELOG.md and per-module CHANGELOG.md files.
func (*Repository) UpdateChangelog ¶
func (r *Repository) UpdateChangelog(release *Release, pending bool) error
UpdateChangelog generates a new CHANGELOG entry for the given release. If pending is true, the contents of CHANGELOG_PENDING.md will be replaced with the new entry. Otherwise, the entry will be prepended to CHANGELOG.md.
func (*Repository) UpdateModuleChangelog ¶
func (r *Repository) UpdateModuleChangelog(release *Release, module string, pending bool) error
UpdateModuleChangelog generates a changelog entry for the specified module, updating the module's CHANGELOG.md file.
func (*Repository) UpdateVersionFiles ¶
func (r *Repository) UpdateVersionFiles(enc VersionEnclosure) error
UpdateVersionFiles updates the version.go file with the version present in the VersionEnclosure enc. If version.go does not exist for a module, UpdateVersionFiles does not create one.
type Version ¶
type Version struct { Module string // Module is the repo relative module path of the Go module. ImportPath string // ImportPath is the full module import path. Version string // Version is a valid Go module semantic version, which can potentially be a pseudo-version. ModuleHash string // ModuleHash is the Go module checksum of the the Version's module. }
Version is the version of a Go module.
type VersionBump ¶
type VersionBump struct { From string // From is the old module version To string // To is the new module version }
VersionBump describes a version increment to a module.
type VersionEnclosure ¶
type VersionEnclosure struct { SchemaVersion int // SchemaVersion is the version of the library's types used to create this VersionEnclosure ModuleVersions map[string]Version // ModuleVersions is a mapping between shortened module paths and their corresponding Version. Packages map[string]string // Packages maps each package in the repo to the shortened module path that provides the package. }
VersionEnclosure is a set of versions for Go modules in a given repository.
type VersionIncrement ¶
type VersionIncrement int
VersionIncrement describes how a Change should affect a module's version.
const ( // NoBump indicates the module's version should not change. NoBump VersionIncrement = iota // PatchBump indicates the module's version should be incremented by a patch version bump. PatchBump // MinorBump indicates the module's version should be incremented by a minor version bump. MinorBump // MajorBump indicates the module's major version should be incremented from v0 to v1. MajorBump // NewModule indicates that a new modules has been discovered and will be assigned a default version. NewModule )
func DevelopmentVersionSelector ¶
func DevelopmentVersionSelector(r *Repository, module string) (string, VersionIncrement, error)
DevelopmentVersionSelector returns a commit hash based version if the module has associated pending Changes, otherwise returns the latest version from the repo's metadata version enclosure.
func ReleaseVersionSelector ¶
func ReleaseVersionSelector(r *Repository, module string) (string, VersionIncrement, error)
ReleaseVersionSelector returns a version for the given module suitable for use during the release process. A version will be returned based upon what type of version bump the Change metadata for the given module requires. ReleaseVersionSelector will properly version modules that are not present in the versions.json file by checking git tags for an existing version, or by providing a default version suitable for the module's major version.
func TaggedVersionSelector ¶
func TaggedVersionSelector(r *Repository, module string) (string, VersionIncrement, error)
TaggedVersionSelector returns the greatest version of module tagged in the git repository.
type VersionSelector ¶
type VersionSelector func(r *Repository, module string) (string, VersionIncrement, error)
VersionSelector is a function that decides what version of a Go module should be passed to code generation.
func (*VersionSelector) Set ¶
func (v *VersionSelector) Set(s string) error
Set parses the input s and correspondingly sets the appropriate VersionSelector.
func (*VersionSelector) String ¶
func (v *VersionSelector) String() string
String returns an empty string to satisfy the flag.Value interface.