diff --git a/.cirrus.yml b/.cirrus.yml index b15d8a2..a3a3f38 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -11,3 +11,38 @@ task: cleanup_script: - tart list - rm -rf ~/.tart/vms/orchard-* + +task: + name: Release Binaries + only_if: $CIRRUS_TAG != '' + depends_on: + - Lint + - Test (macOS) + env: + GITHUB_TOKEN: ENCRYPTED[!98ace8259c6024da912c14d5a3c5c6aac186890a8d4819fad78f3e0c41a4e0cd3a2537dd6e91493952fb056fa434be7c!] + container: + image: goreleaser/goreleaser:latest + cpu: 4 + memory: 12G + release_script: goreleaser + + +docker_builder: + name: Release Docker Image + only_if: $CIRRUS_TAG != '' + depends_on: + - Lint + - Test (macOS) + env: + GITHUB_TOKEN: ENCRYPTED[!82ed873afdf627284305afef4958c85a8f73127b09978a9786ac521559630ea6c9a5ab6e7f8315abf9ead09b6eff6eae!] + login_script: + - echo $GITHUB_TOKEN | docker login ghcr.io -u fkorotkov --password-stdin + setup_script: + - docker buildx create --name multibuilder + - docker buildx use multibuilder + - docker buildx inspect --bootstrap + deploy_script: | + docker buildx build --push --platform linux/amd64,linux/arm64 \ + --tag ghcr.io/cirruslabs/orchard:$CIRRUS_TAG \ + --tag ghcr.io/cirruslabs/orchard:latest \ + . diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..75c13d4 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,41 @@ +project_name: orchard + +before: + hooks: + - go mod download + +builds: + - main: cmd/orchard/main.go + ldflags: > + -X github.com/cirruslabs/orchard/internal/version.Version={{.Version}} + -X github.com/cirruslabs/orchard/internal/version.Commit={{.ShortCommit}} + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + +archives: + - id: binary + format: binary + name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}" + - id: regular + name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}" + +release: + prerelease: auto + +brews: + - name: orchard + ids: + - regular + tap: + owner: cirruslabs + name: homebrew-cli + caveats: See the Github repository for more information + homepage: https://github.com/cirruslabs/orchard + description: Orchestrator for running Tart Virtual Machines on a cluster of Apple Silicon devices + skip_upload: auto diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a008378 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM goreleaser/goreleaser:latest as builder + +WORKDIR /tmp/orchard +ADD . /tmp/orchard/ + +RUN goreleaser build --single-target --snapshot --timeout 60m + +FROM gcr.io/distroless/base + +LABEL org.opencontainers.image.source=https://github.com/cirruslabs/orchard +ENV ORCHARD_HOME=/data +EXPOSE 6120 + +COPY --from=builder /tmp/orchard/dist/orchard_linux_*/orchard /bin/orchard + +CMD ["/bin/orchard"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f411fee --- /dev/null +++ b/LICENSE @@ -0,0 +1,45 @@ +Fair Source License, version 0.9 + +Copyright (C) 2023 Cirrus Labs, Inc. + +Licensor: Cirrus Labs, Inc. + +Software: Orchard + +Use Limitation: 4 users. User is defined as a device running macOS operating system. +The Use Limitation does not apply to devices used by a single individual. + +License Grant. Licensor hereby grants to each recipient of the +Software ("you") a non-exclusive, non-transferable, royalty-free and +fully-paid-up license, under all of the Licensor's copyright and +patent rights, to use, copy, distribute, prepare derivative works of, +publicly perform and display the Software, subject to the Use +Limitation and the conditions set forth below. + +Use Limitation. The license granted above allows use by up to the +number of users per entity set forth above (the "Use Limitation"). For +determining the number of users, "you" includes all affiliates, +meaning legal entities controlling, controlled by, or under common +control with you. If you exceed the Use Limitation, your use is +subject to payment of Licensor's then-current list price for licenses. + +Conditions. Redistribution in source code or other forms must include +a copy of this license document to be provided in a reasonable +manner. Any redistribution of the Software is only allowed subject to +this license. + +Trademarks. This license does not grant you any right in the +trademarks, service marks, brand names or logos of Licensor. + +DISCLAIMER. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OR +CONDITION, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. LICENSORS HEREBY DISCLAIM ALL LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE. + +Termination. If you violate the terms of this license, your rights +will terminate automatically and will not be reinstated without the +prior written consent of Licensor. Any such termination will not +affect the right of others who may have received copies of the +Software from you. diff --git a/go.mod b/go.mod index ee4bb77..32aa645 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/google/uuid v1.3.0 github.com/gosuri/uitable v0.0.4 github.com/hashicorp/go-multierror v1.1.1 + github.com/hashicorp/go-version v1.6.0 github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0 github.com/spf13/cobra v1.6.0 diff --git a/go.sum b/go.sum index 8cf1e3c..c61d9a9 100644 --- a/go.sum +++ b/go.sum @@ -97,6 +97,8 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= diff --git a/internal/command/controller/run.go b/internal/command/controller/run.go index bce492b..8ed10ad 100644 --- a/internal/command/controller/run.go +++ b/internal/command/controller/run.go @@ -5,18 +5,32 @@ import ( "errors" "fmt" "github.com/cirruslabs/orchard/internal/controller" + "github.com/cirruslabs/orchard/internal/netconstants" "github.com/spf13/cobra" "go.uber.org/zap" + "os" + "strconv" ) var ErrRunFailed = errors.New("failed to run controller") +var address string + func newRunCommand() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "run", Short: "Run the controller", RunE: runController, } + + port := os.Getenv("PORT") + if port == "" { + port = strconv.FormatInt(netconstants.DefaultControllerPort, 10) + } + + cmd.PersistentFlags().StringVarP(&address, "listen", "l", fmt.Sprintf(":%s", port), "address to listen on") + + return cmd } func runController(cmd *cobra.Command, args []string) (err error) { @@ -53,6 +67,7 @@ func runController(cmd *cobra.Command, args []string) (err error) { } controller, err := controller.New( + controller.WithListenAddr(address), controller.WithDataDir(dataDir), controller.WithLogger(logger), controller.WithTLSConfig(&tls.Config{ diff --git a/internal/command/root.go b/internal/command/root.go index 969c8b2..af35613 100644 --- a/internal/command/root.go +++ b/internal/command/root.go @@ -11,6 +11,7 @@ import ( "github.com/cirruslabs/orchard/internal/command/portforward" "github.com/cirruslabs/orchard/internal/command/stop" "github.com/cirruslabs/orchard/internal/command/worker" + "github.com/cirruslabs/orchard/internal/version" "github.com/spf13/cobra" ) @@ -19,6 +20,7 @@ func NewRootCmd() *cobra.Command { Use: "orchard", SilenceUsage: true, SilenceErrors: true, + Version: version.FullVersion, } addGroupedCommands(command, "Working With Resources:", diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 0000000..30ab257 --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,33 @@ +package version + +import ( + "fmt" + goversion "github.com/hashicorp/go-version" + "runtime/debug" +) + +var ( + Version = "unknown" + Commit = "unknown" + FullVersion = "" +) + +//nolint:gochecknoinits +func init() { + if Version == "unknown" { + info, ok := debug.ReadBuildInfo() + if ok { + // We parse the version here for two reasons: + // * to weed out the "(devel)" version and fallback to "unknown" instead + // (see https://github.com/golang/go/issues/29228 for details on when this might happen) + // * to remove the "v" prefix from the BuildInfo's version (e.g. "v0.7.0") and thus be consistent + // with the binary builds, where the version string would be "0.7.0" instead + semver, err := goversion.NewSemver(info.Main.Version) + if err == nil { + Version = semver.String() + } + } + } + + FullVersion = fmt.Sprintf("%s-%s", Version, Commit) +}