Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added targets flag for buildpack new cli #1921

Merged
merged 14 commits into from
Oct 17, 2023
22 changes: 22 additions & 0 deletions internal/commands/buildpack_new.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

"github.com/spf13/cobra"


"github.com/buildpacks/pack/internal/style"
"github.com/buildpacks/pack/pkg/client"
"github.com/buildpacks/pack/pkg/dist"
Expand All @@ -19,7 +20,9 @@
type BuildpackNewFlags struct {
API string
Path string
// Deprecated: use `targets` instead
Stacks []string
Targets dist.Targets
Version string
}

Expand Down Expand Up @@ -66,11 +69,22 @@
})
}

var targets dist.Targets
for _, t := range flags.Targets {
targets = append(targets, dist.Target{
OS: t.OS,
Arch: t.Arch,
ArchVariant: t.ArchVariant,
Distributions: t.Distributions,
})
}

if err := creator.NewBuildpack(cmd.Context(), client.NewBuildpackOptions{
API: flags.API,
ID: id,
Path: path,
Stacks: stacks,
Targets: targets,
Version: flags.Version,
}); err != nil {
return err
Expand All @@ -85,6 +99,14 @@
cmd.Flags().StringVarP(&flags.Path, "path", "p", "", "Path to generate the buildpack")
cmd.Flags().StringVarP(&flags.Version, "version", "V", "1.0.0", "Version of the generated buildpack")
cmd.Flags().StringSliceVarP(&flags.Stacks, "stacks", "s", []string{"io.buildpacks.stacks.jammy"}, "Stack(s) this buildpack will be compatible with"+stringSliceHelp("stack"))
cmd.Flags().MarkDeprecated("stacks", "stacks is deprecated in the favor of `targets`")
cmd.Flags().Var(&flags.Targets, "targets",
WYGIN marked this conversation as resolved.
Show resolved Hide resolved
`Targets is a list of platforms that you wish to support. one can provide target platforms in format [os][/arch][/variant]:[name@osversion]
- Base case for two different architectures : '--targets "linux/amd64" --targets "linux/arm64"'
- case for distribution versions: '--targets "windows/amd64:[email protected]"'
- case for different architecture with distrubuted versions : '--targets "linux/arm/v6:[email protected]" --targets "linux/arm/v6:[email protected]"'

Check failure on line 107 in internal/commands/buildpack_new.go

View workflow job for this annotation

GitHub Actions / test (windows-lcow)

`distrubuted` is a misspelling of `distributed` (misspell)
- If no name is provided, a random name will be generated.
`)

AddHelpFlag(cmd, "new")
return cmd
Expand Down
2 changes: 1 addition & 1 deletion pkg/buildpack/buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type Descriptor interface {
Kind() string
Order() dist.Order
Stacks() []dist.Stack
Targets() []dist.Target
Targets() dist.Targets
}

type Blob interface {
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,7 @@ func createInlineBuildpack(bp projectTypes.Buildpack, stackID string) (string, e
bp.Version = "0.0.0"
}

if err = createBuildpackTOML(pathToInlineBuilpack, bp.ID, bp.Version, bp.Script.API, []dist.Stack{{ID: stackID}}, nil); err != nil {
if err = createBuildpackTOML(pathToInlineBuilpack, bp.ID, bp.Version, bp.Script.API, []dist.Stack{{ID: stackID}}, dist.Targets{}, nil); err != nil {
return pathToInlineBuilpack, err
}

Expand Down
10 changes: 7 additions & 3 deletions pkg/client/new_buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ type NewBuildpackOptions struct {
// version of the output buildpack artifact.
Version string

// The stacks this buildpack will work with
// Deprecated: The stacks this buildpack will work with
Stacks []dist.Stack

// the targets this buildpack will work with
Targets dist.Targets
}

func (c *Client) NewBuildpack(ctx context.Context, opts NewBuildpackOptions) error {
err := createBuildpackTOML(opts.Path, opts.ID, opts.Version, opts.API, opts.Stacks, c)
err := createBuildpackTOML(opts.Path, opts.ID, opts.Version, opts.API, opts.Stacks, opts.Targets, c)
if err != nil {
return err
}
Expand Down Expand Up @@ -94,7 +97,7 @@ func createBinScript(path, name, contents string, c *Client) error {
return nil
}

func createBuildpackTOML(path, id, version, apiStr string, stacks []dist.Stack, c *Client) error {
func createBuildpackTOML(path, id, version, apiStr string, stacks []dist.Stack, targets dist.Targets, c *Client) error {
api, err := api.NewVersion(apiStr)
if err != nil {
return err
Expand All @@ -103,6 +106,7 @@ func createBuildpackTOML(path, id, version, apiStr string, stacks []dist.Stack,
buildpackTOML := dist.BuildpackDescriptor{
WithAPI: api,
WithStacks: stacks,
WithTargets: targets,
WithInfo: dist.ModuleInfo{
ID: id,
Version: version,
Expand Down
190 changes: 189 additions & 1 deletion pkg/dist/buildmodule.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dist

import (
"strings"

"github.com/pkg/errors"

"github.com/buildpacks/pack/internal/style"
Expand Down Expand Up @@ -55,10 +57,196 @@
type Target struct {
OS string `json:"os" toml:"os"`
Arch string `json:"arch" toml:"arch"`
Distributions []Distribution `json:"distributions,omitempty" toml:"distributions,omitempty"`
ArchVariant string `json:"variant,omitempty" toml:"variant"`
Distributions Distributions `json:"distributions,omitempty" toml:"distributions,omitempty"`
}

type Targets []Target

func(*Targets) Type() string {
return "Targets"
}

func(targets *Targets) String() string {
var sb strings.Builder
// each target is converted to string & is separated by `,`
for _,t := range *targets {
sb.WriteString(t.String() + ",")
}
return sb.String()
}

// set the value of multiple targets in a single command where each target is separated by a `,` or pass multiple `--targets` to specify each target individually.
func(targets *Targets) Set(value string) error {
// spliting multiple targets into a slice of targets by `,` separater
s := strings.Split(value, ",")
for i,v := range *targets {
// for each individual target set it's value from s[i] & getting an error
err := v.Set(s[i])
// if error is not nill return error
if err != nil {
return err
}
}
return nil
}

func(target *Target) Type() string {
return "Target"
}

// `--target` is passed in the format of `[os][/arch][/variant]:[name@osversion]`
// one can specify multiple distro versions in the format `name@osversion1@osversion2@...`
// one can specify multiple distros seperated by `;`

Check failure on line 100 in pkg/dist/buildmodule.go

View workflow job for this annotation

GitHub Actions / test (windows-lcow)

`seperated` is a misspelling of `separated` (misspell)
// example:
// `name1@osverion1;name2@osversion2;...`
func(target *Target) String() string {
var s string
// if target's OS is not nill append it to string
if target.OS != "" {
s += target.OS
}
// if target's Arch is not nill append it to string
if target.Arch != "" {
// if os is not defined append target's arch without '/'
if s == "" {
s += target.Arch
}
// if os is defined append target's arch separated by '/'
s += "/" + target.Arch
}
// if target's ArchVariant is not nill append it to string
if target.ArchVariant != "" {
// if os and/or arch is/are not defined append target's archVariant without '/'
if s == "" {
s += target.ArchVariant
}
// if os and/or arch is/are not defined append target's archVariant separated by '/'
s += "/" + target.ArchVariant
}

// if distros are nill return the string `s`
if target.Distributions != nil {
// a map of distributions with distro's name as key and versions(slice of string) as value
var v map[string][]string
for _,d := range target.Distributions {
// for each distro add version to map with key as distro's name
v[d.Name] = append(v[d.Name], d.Versions...)

Check failure on line 134 in pkg/dist/buildmodule.go

View workflow job for this annotation

GitHub Actions / test (windows-lcow)

SA5000: assignment to nil map (staticcheck)
}
// after adding all distributions to map
// if [os] or [arch] or [archVariant] is defined append distro to string in format `:[name]@[version1]@[version2];[name1]@[version1]@[version2];`
if s == "" {
for k,d := range v {
if len(d) > 0 {
s += k + "@" + strings.Join(v[k], "@") + ";"
}
// if no version is specified append distro to string in format `[name];[name1];[name2];` without any version
s += k + ";"
}
}
// after adding all distributions to map
// if [os] or [arch] or [archVariant] is defined append distro to string in format `[name]@[version1]@[version2];[name1]@[version1]@[version2];`
s += ":"
for k,d := range v {
if len(d) > 0 {
s += k + "@" + strings.Join(v[k], "@") + ";"
}
s += k + ";"
}
}
// return the final stringified version of target
return s
}

func(target *Target) Set(value string) error {
// each target can only have one `:` to separate [os] [arch] [archVariant] with distro
osDistro := strings.Split(value, ":")
if len(osDistro) > 2 {
return errors.Errorf("invalid format, target should not have more than one `:` separator. got %s number of separators", len(osDistro) - 1)
}
var os, distro string

if len(osDistro) == 2 {
// get the [os][/arch][/archVariant] at index 0 if osDistro is of length 2
os = osDistro[0]
// get [name@osversion] from index 1 if osDistro has length 2
distro = osDistro[1]
} else {
// if osDistro is nil or with length 1 add value of osDistro[0] to
// assign to `os` variable if string has separator '/'
// else assign it to distro
if v := osDistro[0]; strings.ContainsRune(v, '/') {
os = v
} else {
distro = v
}
}
// separate [os] [arch] [archVariant] with separator '/' and assign values to their respective variable
osArch := strings.SplitN(os, "/", 3)
if os := osArch[0]; os != "" {
target.OS = os
}
if arch := osArch[1]; arch != "" {
target.Arch = arch
}
if archVariant := osArch[2]; archVariant != "" {
target.ArchVariant = archVariant
}

// split the distros with the separator ';'
err := target.Distributions.Set(distro)
if err != nil {
return err
}

return nil
}

func(distros *Distributions) String() string {
var s strings.Builder
for _,d := range *distros {
s.WriteString(d.String() + ";")
}
return s.String()
}

func(distros *Distributions) Set(value string) error {
v := strings.Split(value, ";")
for i,d := range *distros {
err := d.Set(v[i])
if err != nil {
return err
}
}
return nil
}

func(distros *Distributions) Type() string {
return "Distributions"
}

func(distro *Distribution) String() string {
return distro.Name + strings.Join(distro.Versions, "@")
}

func(distro *Distribution) Set(value string) error {
v := strings.Split(value, "@")
for i,d := range v {
if i == 0 {
distro.Name = d
}
distro.Versions = append(distro.Versions, d)
}
return nil
}

func(distro *Distribution) Type() string {
return "Distribution"
}

type Distribution struct {
Name string `json:"name,omitempty" toml:"name,omitempty"`
Versions []string `json:"versions,omitempty" toml:"versions,omitempty"`
}

type Distributions []Distribution
4 changes: 2 additions & 2 deletions pkg/dist/buildpack_descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type BuildpackDescriptor struct {
WithAPI *api.Version `toml:"api"`
WithInfo ModuleInfo `toml:"buildpack"`
WithStacks []Stack `toml:"stacks"`
WithTargets []Target `toml:"targets,omitempty"`
WithTargets Targets `toml:"targets,omitempty"`
WithOrder Order `toml:"order"`
WithWindowsBuild bool
WithLinuxBuild bool
Expand Down Expand Up @@ -134,7 +134,7 @@ func (b *BuildpackDescriptor) Stacks() []Stack {
return b.WithStacks
}

func (b *BuildpackDescriptor) Targets() []Target {
func (b *BuildpackDescriptor) Targets() Targets {
return b.WithTargets
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/dist/extension_descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ func (e *ExtensionDescriptor) Stacks() []Stack {
return nil
}

func (e *ExtensionDescriptor) Targets() []Target {
func (e *ExtensionDescriptor) Targets() Targets {
return nil
}
2 changes: 1 addition & 1 deletion pkg/dist/layers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Descriptor interface {
Info() ModuleInfo
Order() Order
Stacks() []Stack
Targets() []Target
Targets() Targets
}

func LayerDiffID(layerTarPath string) (v1.Hash, error) {
Expand Down
Loading