Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 2 additions & 38 deletions cmd/changelog.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"os"
"path/filepath"

"github.com/Masterminds/semver/v3"

"github.com/spf13/cobra"

"github.com/elastic/elastic-package/internal/cobraext"
Expand Down Expand Up @@ -73,9 +71,9 @@ func changelogAddCmd(cmd *cobra.Command, args []string) error {
cobraext.ChangelogAddNextFlagName)
}
if version == "" {
v, err := changelogCmdVersion(nextMode, packageRoot)
v, err := changelog.NextVersion(packageRoot, nextMode)
if err != nil {
return err
return fmt.Errorf("invalid value for %q: %w", cobraext.ChangelogAddNextFlagName, err)
}
version = v.String()
}
Expand Down Expand Up @@ -108,40 +106,6 @@ func changelogAddCmd(cmd *cobra.Command, args []string) error {
return nil
}

func changelogCmdVersion(nextMode, packageRoot string) (*semver.Version, error) {
revisions, err := changelog.ReadChangelogFromPackageRoot(packageRoot)
if err != nil {
return nil, fmt.Errorf("failed to read current changelog: %w", err)
}
if len(revisions) == 0 {
return semver.MustParse("0.0.0"), nil
}

version, err := semver.NewVersion(revisions[0].Version)
if err != nil {
return nil, fmt.Errorf("invalid version in changelog %q: %w", revisions[0].Version, err)
}

switch nextMode {
case "":
break
case "major":
v := version.IncMajor()
version = &v
case "minor":
v := version.IncMinor()
version = &v
case "patch":
v := version.IncPatch()
version = &v
default:
return nil, fmt.Errorf("invalid value for %q: %s",
cobraext.ChangelogAddNextFlagName, nextMode)
}

return version, nil
}

// patchChangelogFile looks for the proper place to add the new revision in the changelog,
// trying to conserve original format and comments.
func patchChangelogFile(packageRoot string, patch changelog.Revision) error {
Expand Down
84 changes: 74 additions & 10 deletions cmd/requires.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ func setupRequiresCommand() *cobraext.Command {
updateCmd.Flags().Bool(cobraext.RequiresDryRunFlagName, false, cobraext.RequiresDryRunFlagDescription)
updateCmd.Flags().String(cobraext.RequiresFormatFlagName, requiresFormatTable, fmt.Sprintf(cobraext.RequiresFormatFlagDescription, strings.Join(requiresFormatChoices, "|")))
updateCmd.Flags().Bool(cobraext.RequiresPrereleaseFlagName, false, cobraext.RequiresPrereleaseFlagDescription)
updateCmd.Flags().Bool(cobraext.RequiresChangelogFlagName, false, cobraext.RequiresChangelogFlagDescription)
updateCmd.Flags().String(cobraext.RequiresChangelogTypeFlagName, "", cobraext.RequiresChangelogTypeFlagDescription)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no documentation added for these 2 new flags here:

requiresUpdateLongDescription = `Update requires.input and requires.content pins to the latest registry versions compatible with this package's Kibana constraint.
By default manifest.yml is updated. Use --dry-run to report available bumps without writing the manifest.
Version pins must be exact semver versions (constraints such as ^0.3.0 are not accepted).
When a newer dependency exists but requires a higher Kibana version than this package allows, a warning is printed suggesting to bump conditions.kibana.version on the integration package.`


cmd := &cobra.Command{
Use: "requires",
Expand All @@ -70,6 +72,13 @@ const (

var requiresFormatChoices = []string{requiresFormatTable, requiresFormatJSON}

// changelogTypeChoices mirrors the changelog entry type enum defined in the package-spec
// (spec/integration/changelog.spec.yml). The canonical validation happens when the
// package is built and checked against the spec; this list enables early flag
// validation. "deprecation" is intentionally excluded as it is not a valid type
// for automated dependency-bump changelog entries.
var changelogTypeChoices = []string{"bugfix", "enhancement", "breaking-change"}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking a look to this list, there is another place where these values are king of defined.

ChangelogAddTypeFlagDescription = "type of change (bugfix, enhancement or breaking-change) for the changelog entry"

I know that this is unrelated to tihs PR, but could you add deprecation there in the flag description?

I wonder if we could set the list in the description programmatically.


func requiresUpdateCommandAction(cmd *cobra.Command, _ []string) error {
dryRun, err := cmd.Flags().GetBool(cobraext.RequiresDryRunFlagName)
if err != nil {
Expand All @@ -86,6 +95,20 @@ func requiresUpdateCommandAction(cmd *cobra.Command, _ []string) error {
if err != nil {
return cobraext.FlagParsingError(err, cobraext.RequiresPrereleaseFlagName)
}
changelogEnabled, err := cmd.Flags().GetBool(cobraext.RequiresChangelogFlagName)
if err != nil {
return cobraext.FlagParsingError(err, cobraext.RequiresChangelogFlagName)
}
changelogType, err := cmd.Flags().GetString(cobraext.RequiresChangelogTypeFlagName)
if err != nil {
return cobraext.FlagParsingError(err, cobraext.RequiresChangelogTypeFlagName)
}
if changelogType != "" && !changelogEnabled {
return fmt.Errorf("--%s requires --%s", cobraext.RequiresChangelogTypeFlagName, cobraext.RequiresChangelogFlagName)
}
if changelogType != "" && !slices.Contains(changelogTypeChoices, changelogType) {
return fmt.Errorf("unsupported changelog type %q, supported types: %s", changelogType, strings.Join(changelogTypeChoices, ", "))
}

packageRoot, err := packages.MustFindPackageRoot()
if err != nil {
Expand Down Expand Up @@ -123,19 +146,11 @@ func requiresUpdateCommandAction(cmd *cobra.Command, _ []string) error {
return p.Proposed != ""
})
if !dryRun && hasBumps {
manifestPath := filepath.Join(packageRoot, packages.PackageManifestFile)
manifestBytes, err := os.ReadFile(manifestPath)
if err != nil {
return fmt.Errorf("reading manifest file failed: %w", err)
}
manifestBytes, err = requiresupdates.Apply(manifestBytes, result.Proposals)
newVersion, err := applyRequiresUpdate(packageRoot, result.Proposals, changelogEnabled, changelogType)
if err != nil {
return err
}
logger.Debugf("writing updated manifest: %s", manifestPath)
if err := os.WriteFile(manifestPath, manifestBytes, 0o644); err != nil {
return fmt.Errorf("writing manifest file failed: %w", err)
}
result.NewVersion = newVersion
applied = true
}

Expand All @@ -155,6 +170,24 @@ func requiresUpdateCommandAction(cmd *cobra.Command, _ []string) error {

if dryRun && hasBumps {
cmd.Println("Dry run: manifest.yml was not modified")
if changelogEnabled {
tier := requiresupdates.AggregateTier(result.Proposals)
next, err := requiresupdates.NextVersion(tier, packageRoot)
if err != nil {
return err
}
cmd.Printf("Dry run: would bump package version to %s and add changelog entries:\n", next)
for _, p := range result.Proposals {
if p.Proposed == "" {
continue
}
t := changelogType
if t == "" {
t = requiresupdates.DefaultChangelogType(p.Tier())
}
cmd.Printf(" - [%s] %s: %s -> %s\n", t, p.Package, p.Current, p.Proposed)
}
}
} else if applied {
cmd.Println("Updated manifest.yml")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If --changelog is set, this message should also indicate that changelog.yml has been updated.

} else if len(result.Proposals) == 0 && result.SkipReason == "" {
Expand All @@ -164,6 +197,37 @@ func requiresUpdateCommandAction(cmd *cobra.Command, _ []string) error {
return nil
}

// applyRequiresUpdate orchestrates the two-step write: first updates requires
// pins via requiresupdates.Apply, then (when changelogEnabled) bumps the package
// version and patches changelog.yml via requiresupdates.ApplyChangelog.
// Returns the new package version when --changelog bumped it ("" otherwise).
// Caller guarantees there is at least one bump (Proposed != "") in proposals.
func applyRequiresUpdate(packageRoot string, proposals []requiresupdates.UpdateProposal, changelogEnabled bool, changelogType string) (newVersion string, err error) {
manifestPath := filepath.Join(packageRoot, packages.PackageManifestFile)
manifestBytes, err := os.ReadFile(manifestPath)
if err != nil {
return "", fmt.Errorf("reading manifest file failed: %w", err)
}

manifestBytes, err = requiresupdates.Apply(manifestBytes, proposals)
if err != nil {
return "", err
}

if changelogEnabled {
manifestBytes, newVersion, err = requiresupdates.ApplyChangelog(packageRoot, manifestBytes, proposals, changelogType)
if err != nil {
return "", err
}
}

logger.Debugf("writing updated manifest: %s", manifestPath)
if err := os.WriteFile(manifestPath, manifestBytes, 0o644); err != nil {
return "", fmt.Errorf("writing manifest file failed: %w", err)
}
return newVersion, nil
}

func printRequiresUpdateResult(result *requiresupdates.Result, w io.Writer, format string) error {
if result == nil {
return nil
Expand Down
Loading