Skip to content

Commit

Permalink
feat: Add Swift provider and Vapor support
Browse files Browse the repository at this point in the history
  • Loading branch information
yuaanlin committed Dec 20, 2023
1 parent 9ef358d commit f13847e
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 1 deletion.
30 changes: 30 additions & 0 deletions internal/swift/identify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package swift

Check warning on line 1 in internal/swift/identify.go

View workflow job for this annotation

GitHub Actions / lint

package-comments: should have a package comment (revive)

import (
"github.com/spf13/afero"

"github.com/zeabur/zbpack/internal/utils"
"github.com/zeabur/zbpack/pkg/plan"
"github.com/zeabur/zbpack/pkg/types"
)

type identify struct{}

// NewIdentifier returns a new Python identifier.
func NewIdentifier() plan.Identifier {
return &identify{}
}

func (i *identify) PlanType() types.PlanType {
return types.PlanTypeSwift
}

func (i *identify) Match(fs afero.Fs) bool {
return utils.HasFile(fs, "Package.swift")
}

func (i *identify) PlanMeta(options plan.NewPlannerOptions) types.PlanMeta {
return GetMeta(GetMetaOptions{Src: options.Source, Config: options.Config})
}

var _ plan.Identifier = (*identify)(nil)
62 changes: 62 additions & 0 deletions internal/swift/plan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package swift

import (
"github.com/moznion/go-optional"
"github.com/spf13/afero"
"github.com/zeabur/zbpack/internal/utils"
"github.com/zeabur/zbpack/pkg/plan"
"github.com/zeabur/zbpack/pkg/types"
)

type swiftPlanContext struct {
Src afero.Fs
Config plan.ImmutableProjectConfiguration
Framework optional.Option[types.SwiftFramework]
}

// DetermineFramework determines the framework of the Swift project.
func DetermineFramework(ctx *swiftPlanContext) types.SwiftFramework {
src := ctx.Src
fw := &ctx.Framework

if framework, err := fw.Take(); err == nil {
return framework
}

content, err := afero.ReadFile(src, "Package.swift")
if err != nil {
*fw = optional.Some(types.SwiftFrameworkNone)
return fw.Unwrap()
}

if utils.WeakContains(string(content), "https://github.com/vapor/vapor.git") {
*fw = optional.Some(types.SwiftFrameworkVapor)
return fw.Unwrap()
}

*fw = optional.Some(types.SwiftFrameworkNone)
return fw.Unwrap()
}

// GetMetaOptions is the options for GetMeta.
type GetMetaOptions struct {
Src afero.Fs
Config plan.ImmutableProjectConfiguration
}

// GetMeta returns the metadata of a Swift project.
func GetMeta(opt GetMetaOptions) types.PlanMeta {
meta := types.PlanMeta{}

ctx := &swiftPlanContext{
Src: opt.Src,
Config: opt.Config,
}

framework := DetermineFramework(ctx)
if framework != types.SwiftFrameworkNone {
meta["framework"] = string(framework)
}

return meta
}
79 changes: 79 additions & 0 deletions internal/swift/swift.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package swift

import (
"github.com/zeabur/zbpack/pkg/packer"
"github.com/zeabur/zbpack/pkg/types"
)

type pack struct {
*identify
}

func NewPacker() packer.Packer {

Check warning on line 12 in internal/swift/swift.go

View workflow job for this annotation

GitHub Actions / lint

exported: exported function NewPacker should have comment or be unexported (revive)
return &pack{
identify: &identify{},
}
}

func GenerateDockerfile(meta types.PlanMeta) (string, error) {

Check warning on line 18 in internal/swift/swift.go

View workflow job for this annotation

GitHub Actions / lint

exported: exported function GenerateDockerfile should have comment or be unexported (revive)

// TODO: following dockerfile is copied from Vapor's template, need to be modified to support other Swift use cases
return `FROM swift:5.9-jammy as build
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
&& apt-get -q update \
&& apt-get -q dist-upgrade -y \
&& apt-get install -y libjemalloc-dev
WORKDIR /build
COPY ./Package.* ./
RUN swift package resolve --skip-update \
$([ -f ./Package.resolved ] && echo "--force-resolved-versions" || true)
COPY . .
RUN swift build -c release \
--static-swift-stdlib \
-Xlinker -ljemalloc
WORKDIR /staging
RUN cp "$(swift build --package-path /build -c release --show-bin-path)/App" ./
RUN cp "/usr/libexec/swift/linux/swift-backtrace-static" ./
RUN find -L "$(swift build --package-path /build -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \;
RUN [ -d /build/Public ] && { mv /build/Public ./Public && chmod -R a-w ./Public; } || true
RUN [ -d /build/Resources ] && { mv /build/Resources ./Resources && chmod -R a-w ./Resources; } || true
FROM ubuntu:jammy
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
&& apt-get -q update \
&& apt-get -q dist-upgrade -y \
&& apt-get -q install -y \
libjemalloc2 \
ca-certificates \
tzdata \
libcurl4 \
libxml2 \
&& rm -r /var/lib/apt/lists/*
WORKDIR /app
COPY --from=build --chown=vapor:vapor /staging /app
ENV SWIFT_BACKTRACE=enable=yes,sanitize=yes,threads=all,images=all,interactive=no,swift-backtrace=./swift-backtrace-static
ENTRYPOINT ["./App"]
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
`, nil
}

func (p *pack) GenerateDockerfile(meta types.PlanMeta) (string, error) {
return GenerateDockerfile(meta)
}

var _ packer.Packer = (*pack)(nil)
9 changes: 9 additions & 0 deletions pkg/types/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
PlanTypeElixir PlanType = "elixir"
PlanTypeBun PlanType = "bun"
PlanTypeStatic PlanType = "static"
PlanTypeSwift PlanType = "swift"
)

//revive:enable:exported
Expand Down Expand Up @@ -98,6 +99,14 @@ const (
PythonPackageManagerPdm PythonPackageManager = "pdm"
)

type SwiftFramework string

//revive:disable:exported
const (
SwiftFrameworkVapor SwiftFramework = "vapor"
SwiftFrameworkNone SwiftFramework = "none"
)

//revive:enable:exported

// JavaProjectType represents the type of a Java project.
Expand Down
2 changes: 2 additions & 0 deletions pkg/zeaburpack/identifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/zeabur/zbpack/internal/ruby"
"github.com/zeabur/zbpack/internal/rust"
"github.com/zeabur/zbpack/internal/static"
"github.com/zeabur/zbpack/internal/swift"
"github.com/zeabur/zbpack/pkg/plan"
)

Expand All @@ -33,6 +34,7 @@ func SupportedIdentifiers() []plan.Identifier {
rust.NewIdentifier(),
dotnet.NewIdentifier(),
elixir.NewIdentifier(),
swift.NewIdentifier(),
static.NewIdentifier(),
}
}
2 changes: 1 addition & 1 deletion pkg/zeaburpack/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func buildImage(opt *buildImageOptions) error {
return fmt.Errorf("run buildctl build: %w", err)
}

if !strings.Contains(buildctlCmd.String(), "--type=docker") {
if !strings.Contains(buildctlCmd.String(), "type=docker") {
return nil // buildctl have handled push
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/zeaburpack/packers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/zeabur/zbpack/internal/ruby"
"github.com/zeabur/zbpack/internal/rust"
"github.com/zeabur/zbpack/internal/static"
"github.com/zeabur/zbpack/internal/swift"
"github.com/zeabur/zbpack/pkg/packer"
)

Expand All @@ -32,6 +33,7 @@ func SupportedPackers() []packer.Packer {
rust.NewPacker(),
dotnet.NewPacker(),
elixir.NewPacker(),
swift.NewPacker(),
static.NewPacker(),
}
}

0 comments on commit f13847e

Please sign in to comment.