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

Update check #866

Merged
merged 3 commits into from
Aug 3, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ $(BUILD_DIR)/$(PROJECT)-%-$(GOARCH): $(GO_FILES) $(BUILD_DIR)
%.exe: %
cp $< $@

.PHONY: $(BUILD_DIR)/VERSION
$(BUILD_DIR)/VERSION:
@ echo $(VERSION) > $@

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

Expand All @@ -79,12 +83,13 @@ integration: install $(BUILD_DIR)/$(PROJECT)
go test -v -tags integration $(REPOPATH)/integration -timeout 10m --remote=$(REMOTE_INTEGRATION)

.PHONY: release
release: cross docs
release: cross docs $(BUILD_DIR)/VERSION
docker build \
-f deploy/skaffold/Dockerfile \
--cache-from gcr.io/$(GCP_PROJECT)/skaffold-builder \
-t gcr.io/$(GCP_PROJECT)/skaffold:$(VERSION) .
gsutil -m cp $(BUILD_DIR)/$(PROJECT)-* $(GSC_RELEASE_PATH)/
gsutil -m cp $(BUILD_DIR)/VERISON $(GSC_RELEASE_PATH)/VERISON
gsutil -m cp -r $(DOCS_DIR)/* $(GSC_RELEASE_PATH)/docs/
gsutil -m cp -r $(GSC_RELEASE_PATH)/* $(GSC_RELEASE_LATEST)

Expand Down
37 changes: 37 additions & 0 deletions cmd/skaffold/app/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ limitations under the License.
package cmd

import (
"context"
"fmt"
"io"

cmdutil "github.com/GoogleContainerTools/skaffold/cmd/skaffold/app/cmd/util"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/update"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/version"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand All @@ -33,6 +36,8 @@ var (
v string
filename string
overwrite bool

updateMsg = make(chan string)
)

var rootCmd = &cobra.Command{
Expand All @@ -47,9 +52,22 @@ func NewSkaffoldCommand(out, err io.Writer) *cobra.Command {
}
rootCmd.SilenceUsage = true
logrus.Infof("Skaffold %+v", version.Get())
go func() {
if err := updateCheck(updateMsg); err != nil {
logrus.Infof("update check failed: %s", err)
}
}()
return nil
}

rootCmd.PersistentPostRun = func(cmd *cobra.Command, args []string) {
select {
case msg := <-updateMsg:
fmt.Fprintf(out, "%s\n", msg)
default:
}
}

rootCmd.SilenceErrors = true
rootCmd.AddCommand(NewCmdCompletion(out))
rootCmd.AddCommand(NewCmdVersion(out))
Expand All @@ -64,6 +82,25 @@ func NewSkaffoldCommand(out, err io.Writer) *cobra.Command {
return rootCmd
}

func updateCheck(ch chan string) error {
if !update.IsUpdateCheckEnabled() {
logrus.Debugf("Update check not enabled, skipping.")
return nil
}
current, err := version.ParseVersion(version.Get().Version)
if err != nil {
return errors.Wrap(err, "parsing current semver, skipping update check")
}
latest, err := update.GetLatestVersion(context.Background())
if err != nil {
return errors.Wrap(err, "getting latest version")
}
if latest.GT(current) {
ch <- fmt.Sprintf("There is a new version (%s) of skaffold available. Download it at %s\n", latest, constants.LatestDownloadURL)
}
return nil
}

func AddDevFlags(cmd *cobra.Command) {
cmd.Flags().BoolVar(&opts.Cleanup, "cleanup", true, "Delete deployments after dev mode is interrupted")
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/skaffold/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ limitations under the License.
package constants

import (
"fmt"
"runtime"

"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -45,10 +48,14 @@ const (

DefaultKanikoImage = "gcr.io/kaniko-project/executor:v0.2.0@sha256:bebe80bb97950d88b8d8eab315a58e0bc50307135cf25147d7e0b8f3db50a84a"
DefaultKanikoSecretName = "kaniko-secret"

UpdateCheckEnvironmentVariable = "SKAFFOLD_UPDATE_CHECK"
)

var DefaultKubectlManifests = []string{"k8s/*.yaml"}

var LatestDownloadURL = fmt.Sprintf("https://storage.googleapis.com/skaffold/releases/latest/skaffold-%s-%s", runtime.GOOS, runtime.GOARCH)

var Labels = struct {
TagPolicy string
Deployer string
Expand Down
68 changes: 68 additions & 0 deletions pkg/skaffold/update/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Copyright 2018 The Skaffold Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package update

import (
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"

"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/version"
"github.com/blang/semver"
"github.com/pkg/errors"
)

// IsUpdateCheckEnabled returns whether or not the update check is enabled
// It is true by default, but setting it to any other value than true will disable the check
func IsUpdateCheckEnabled() bool {
// Don't perform a version check on dirty trees
if version.Get().GitTreeState == "dirty" {
return false
}
v := os.Getenv(constants.UpdateCheckEnvironmentVariable)
if v == "" || strings.ToLower(v) == "true" {
return true
}
return false
}

var latestVersionURL = fmt.Sprintf("https://storage.googleapis.com/skaffold/releases/latest/VERSION")

// GetLatestVersion uses a VERSION file stored on GCS to determine the latest released version of skaffold
func GetLatestVersion(ctx context.Context) (semver.Version, error) {
resp, err := http.Get(latestVersionURL)
if err != nil {
return semver.Version{}, errors.Wrap(err, "getting latest version info from GCS")
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return semver.Version{}, errors.Wrapf(err, "http %d, error: %s", resp.StatusCode, resp.Status)
}
versionBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return semver.Version{}, errors.Wrap(err, "reading version file from GCS")
}
v, err := version.ParseVersion(string(versionBytes))
if err != nil {
return semver.Version{}, errors.Wrap(err, "parsing latest version from GCS")
}
return v, nil
}
14 changes: 14 additions & 0 deletions pkg/skaffold/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ package version
import (
"fmt"
"runtime"
"strings"

"github.com/blang/semver"
"github.com/pkg/errors"
)

var version, gitCommit, gitTreeState, buildDate string
Expand Down Expand Up @@ -52,3 +56,13 @@ func Get() *Info {
func UserAgent() string {
return fmt.Sprintf("skaffold/%s/%s", platform, version)
}

func ParseVersion(version string) (semver.Version, error) {
// Strip the leading 'v' in our version strings
version = strings.TrimSpace(version)
v, err := semver.Parse(strings.TrimLeft(version, "v"))
if err != nil {
return semver.Version{}, errors.Wrap(err, "parsing semver")
}
return v, nil
}
56 changes: 56 additions & 0 deletions pkg/skaffold/version/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2018 The Skaffold Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

import (
"testing"

"github.com/GoogleContainerTools/skaffold/testutil"
"github.com/blang/semver"
)

func TestParseVersion(t *testing.T) {
var tests = []struct {
description string
in string
out semver.Version
shouldErr bool
}{
{
description: "parse version correct",
in: "v0.10.0",
out: semver.MustParse("0.10.0"),
},
{
description: "parse version correct without leading v",
in: "0.10.0",
out: semver.MustParse("0.10.0"),
},
{
description: "parse error",
in: "notasemver",
shouldErr: true,
},
}

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
actual, err := ParseVersion(test.in)
testutil.CheckErrorAndDeepEqual(t, test.shouldErr, err, test.out, actual)
})
}
}
22 changes: 22 additions & 0 deletions vendor/github.com/blang/semver/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions vendor/github.com/blang/semver/json.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading