Deliver module releases to full-tag pages
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/candidate"
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/git"
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/gitea"
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/gotool"
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/releaseidentity"
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/tempdir"
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/versioncontract"
|
||||
@@ -33,6 +34,7 @@ type Request struct {
|
||||
ModuleDir string
|
||||
Product string
|
||||
Version string
|
||||
ExpectedTag string
|
||||
Destination gitea.Destination
|
||||
Build *internalbuild.Spec
|
||||
Prebuilt *internalbuild.Result
|
||||
@@ -69,36 +71,51 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("resolve repository directory: %w", err)
|
||||
}
|
||||
source, err := git.InspectTaggedSource(ctx, repositoryDir, request.Version)
|
||||
result.RepositoryDir = repositoryDir
|
||||
selection, err := releaseidentity.ResolveSelection(repositoryDir, request.ModuleDir)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("inspect tagged source: %w", err)
|
||||
return result, fmt.Errorf("resolve delivery module: %w", err)
|
||||
}
|
||||
result.CandidateCommit = source.TagCommit
|
||||
if source.Status != "" {
|
||||
return result, fmt.Errorf("tagged checkout must be clean:\n%s", source.Status)
|
||||
}
|
||||
if source.Head != source.TagCommit {
|
||||
return result, fmt.Errorf("checkout HEAD %s does not match tag %s commit %s", source.Head, request.Version, source.TagCommit)
|
||||
}
|
||||
notePath := "docs/releases/" + request.Version + ".md"
|
||||
note, err := git.ReadCommitFile(ctx, repositoryDir, source.TagCommit, notePath)
|
||||
result.ModuleDir = selection.ModuleDir
|
||||
commit, err := git.CaptureHead(ctx, repositoryDir)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result.CandidateCommit = commit
|
||||
identity, err := releaseidentity.FromCommittedSelection(ctx, selection, request.Version, commit)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("resolve committed delivery identity: %w", err)
|
||||
}
|
||||
result.RepositoryDir = identity.RepositoryDir
|
||||
result.ModuleDir = identity.ModuleDir
|
||||
result.ModulePath = identity.ModulePath
|
||||
result.Tag = identity.Tag
|
||||
if request.ExpectedTag != "" && request.ExpectedTag != identity.Tag {
|
||||
return result, fmt.Errorf("expected delivery tag %q does not match selected module tag %q", request.ExpectedTag, identity.Tag)
|
||||
}
|
||||
source, err := git.InspectTaggedSource(ctx, repositoryDir, identity.Tag)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("inspect tagged source: %w", err)
|
||||
}
|
||||
if source.Status != "" {
|
||||
return result, fmt.Errorf("tagged checkout must be clean:\n%s", source.Status)
|
||||
}
|
||||
if source.Head != commit {
|
||||
return result, fmt.Errorf("checkout HEAD changed from captured commit %s to %s", commit, source.Head)
|
||||
}
|
||||
if source.TagCommit != commit {
|
||||
return result, fmt.Errorf("checkout HEAD %s does not match tag %s commit %s", source.Head, identity.Tag, source.TagCommit)
|
||||
}
|
||||
note, err := git.ReadCommitFile(ctx, repositoryDir, commit, identity.NotePath)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("read release note %q: %w", identity.NotePath, err)
|
||||
}
|
||||
if err := candidate.ValidateReleaseNote(note, request.Product, request.Version); err != nil {
|
||||
return result, fmt.Errorf("release note %q: %w", notePath, err)
|
||||
return result, fmt.Errorf("release note %q: %w", identity.NotePath, err)
|
||||
}
|
||||
|
||||
build := request.Prebuilt
|
||||
if request.Build != nil && len(request.Build.Targets) != 0 {
|
||||
selection, err := releaseidentity.ResolveSelection(repositoryDir, request.ModuleDir)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("resolve managed build module: %w", err)
|
||||
}
|
||||
identity, err := releaseidentity.FromCommittedSelection(ctx, selection, request.Version, source.TagCommit)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("resolve managed build identity: %w", err)
|
||||
}
|
||||
temporaryDir, err := tempdir.Outside(repositoryDir, "releasekit-delivery-build-*")
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("create temporary delivery build directory: %w", err)
|
||||
@@ -109,6 +126,7 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
Spec: *request.Build,
|
||||
OutputDir: filepath.Join(temporaryDir, "assets"),
|
||||
Output: request.Output,
|
||||
ToolOwner: gotool.NewOwner(identity.ModuleDir),
|
||||
})
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("build delivery assets: %w", err)
|
||||
@@ -122,7 +140,7 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
if err := validateBuild(repositoryDir, source.TagCommit, request.Version, build, assets); err != nil {
|
||||
if err := validateBuild(identity, commit, build, assets); err != nil {
|
||||
return result, err
|
||||
}
|
||||
if len(assets) > 0 {
|
||||
@@ -131,22 +149,22 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
}
|
||||
}
|
||||
if build != nil && len(build.Settings.Targets) != 0 {
|
||||
current, err := git.InspectTaggedSource(ctx, repositoryDir, request.Version)
|
||||
current, err := git.InspectTaggedSource(ctx, repositoryDir, identity.Tag)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("recheck tagged source after build: %w", err)
|
||||
}
|
||||
if current.Status != "" {
|
||||
return result, fmt.Errorf("tagged checkout changed during build:\n%s", current.Status)
|
||||
}
|
||||
if current.Head != source.TagCommit || current.TagCommit != source.TagCommit {
|
||||
if current.Head != commit || current.TagCommit != commit {
|
||||
return result, errors.New("tagged source changed during build")
|
||||
}
|
||||
}
|
||||
|
||||
releaseResult, err := (gitea.Client{}).EnsureRelease(ctx, gitea.Request{
|
||||
Destination: request.Destination,
|
||||
Version: request.Version,
|
||||
Commit: source.TagCommit,
|
||||
Tag: identity.Tag,
|
||||
Commit: commit,
|
||||
Note: string(note),
|
||||
})
|
||||
if err != nil {
|
||||
@@ -180,13 +198,24 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
return result, uploadErr
|
||||
}
|
||||
|
||||
func validateBuild(repositoryDir, commit, version string, build *internalbuild.Result, assets []gitea.ExpectedAsset) error {
|
||||
func validateBuild(identity releaseidentity.Identity, commit string, build *internalbuild.Result, assets []gitea.ExpectedAsset) error {
|
||||
if build == nil {
|
||||
if len(assets) != 0 {
|
||||
return errors.New("assets require a build identity")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
buildRepository, err := filepath.Abs(build.RepositoryDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve build repository: %w", err)
|
||||
}
|
||||
buildModule, err := filepath.Abs(build.ModuleDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve build module: %w", err)
|
||||
}
|
||||
if buildRepository != identity.RepositoryDir || buildModule != identity.ModuleDir || build.ModulePath != identity.ModulePath || build.Tag != identity.Tag || build.CandidateCommit != commit || build.Version != identity.Version {
|
||||
return errors.New("build result does not identify the selected tagged module")
|
||||
}
|
||||
if len(build.Settings.Targets) == 0 {
|
||||
if len(assets) != 0 {
|
||||
return errors.New("page-only delivery cannot include binary assets")
|
||||
@@ -196,13 +225,6 @@ func validateBuild(repositoryDir, commit, version string, build *internalbuild.R
|
||||
if !build.SourceVerified {
|
||||
return errors.New("build source was not verified as clean and unchanged during compilation")
|
||||
}
|
||||
buildRepository, err := filepath.Abs(build.RepositoryDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve build repository: %w", err)
|
||||
}
|
||||
if buildRepository != repositoryDir || build.CandidateCommit != commit || build.Version != version {
|
||||
return errors.New("build result does not identify the selected tagged source")
|
||||
}
|
||||
if strings.TrimSpace(build.Settings.MainPackage) == "" || strings.TrimSpace(build.Settings.BinaryName) == "" || len(assets) != len(build.Settings.Targets)+1 || assets[len(assets)-1].Filename != gitea.ManifestFilename {
|
||||
return errors.New("build result does not contain the selected artifacts and complete checksum manifest")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user