From 53fde93499d154260376985a19fb8a4be8448312 Mon Sep 17 00:00:00 2001 From: Akos Birmacher <37296013+BirmacherAkos@users.noreply.github.com> Date: Fri, 22 Mar 2019 15:41:53 +0100 Subject: [PATCH] Add Session support (#43) * new sample app * add fastlane_session feature * add project path env to the sample app * wire in the session * dep add github.com/bitrise-tools/go-steputils/tools * fix project path * - * clean * using fastlane devportalservice package from the isunes-connect-deliver step for FASTLANE_SESSION * add github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/devportalservice dependency --- Gopkg.lock | 18 +++ Gopkg.toml | 8 + bitrise.yml | 14 +- main.go | 25 +++ .../LICENSE | 22 +++ .../devportalservice/devportalservice.go | 151 ++++++++++++++++++ .../bitrise-tools/go-steputils/tools/tools.go | 14 ++ 7 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/LICENSE create mode 100644 vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/devportalservice/devportalservice.go create mode 100644 vendor/github.com/bitrise-tools/go-steputils/tools/tools.go diff --git a/Gopkg.lock b/Gopkg.lock index e3afc1f..e6875cd 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -17,6 +17,22 @@ pruneopts = "UT" revision = "2a09aab8380d7842750328aebd5671bcccea89c8" +[[projects]] + branch = "master" + digest = "1:a3b919ac82ab21667747cd674a4090889bb1a0c4570e093eb6d0c61f7a01064f" + name = "github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver" + packages = ["devportalservice"] + pruneopts = "UT" + revision = "80467e08fd63e3f11dd03e08ed8ccca716ef49d4" + +[[projects]] + branch = "master" + digest = "1:659157c334882ba37fe50584d691ea469fb6e708a49e81dcd4381fef6ba611b0" + name = "github.com/bitrise-tools/go-steputils" + packages = ["tools"] + pruneopts = "UT" + revision = "ec226b2359fcd806be64f0ad2217d8e741a1ff11" + [[projects]] digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" name = "github.com/davecgh/go-spew" @@ -61,6 +77,8 @@ "github.com/bitrise-io/go-utils/fileutil", "github.com/bitrise-io/go-utils/log", "github.com/bitrise-io/go-utils/pathutil", + "github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/devportalservice", + "github.com/bitrise-tools/go-steputils/tools", "github.com/kballard/go-shellquote", "github.com/stretchr/testify/require", ] diff --git a/Gopkg.toml b/Gopkg.toml index cde0eff..8d09b51 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -13,3 +13,11 @@ [prune] go-tests = true unused-packages = true + +[[constraint]] + branch = "master" + name = "github.com/bitrise-tools/go-steputils" + +[[constraint]] + branch = "master" + name = "github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver" diff --git a/bitrise.yml b/bitrise.yml index 92dc517..2ae6480 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -3,8 +3,10 @@ default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git app: envs: - - SAMPLE_APP_URL: "https://github.com/bitrise-samples/sample-apps-ios-simple-objc-with-uitest.git" - - LANE: tests + - SAMPLE_APP_URL: "https://github.com/bitrise-samples/sample-apps-fastlane-test.git" + - LANE: release + - BITRISE_PROJECT_PATH: ./sample-apps-fastlane-test.xcodeproj + - BITRISE_SCHEME: sample-apps-fastlane-test workflows: # ---------------------------------------------------------------- @@ -28,11 +30,15 @@ workflows: - is_create_path: true - script: inputs: - - content: git clone $SAMPLE_APP_URL -b fastlane . + - content: git clone $SAMPLE_APP_URL . + - ios-auto-provision@1.3.1: + inputs: + - generate_profiles: 'yes' + - distribution_type: app-store - path::./: inputs: - lane: $LANE - - work_dir: ios-simple-objc + - work_dir: ./ # ---------------------------------------------------------------- # --- Utility workflows diff --git a/main.go b/main.go index d07a5ca..bb37cc9 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,8 @@ import ( "github.com/bitrise-io/go-utils/fileutil" "github.com/bitrise-io/go-utils/log" "github.com/bitrise-io/go-utils/pathutil" + "github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/devportalservice" + "github.com/bitrise-tools/go-steputils/tools" shellquote "github.com/kballard/go-shellquote" ) @@ -139,6 +141,29 @@ func main() { log.Donef("Expanded WorkDir: %s", workDir) + // + // Fastlane session + fmt.Println() + log.Infof("Ensure cookies for Apple Developer Portal") + + fs, errors := devportalservice.SessionData() + if errors != nil { + log.Warnf("Failed to activate the Bitrise Apple Developer Portal connection: %s\nRead more: https://devcenter.bitrise.io/getting-started/signing-up/connecting-apple-dev-account/\nerrors:") + for _, err := range errors { + log.Errorf("%s\n", err) + } + } else { + if err := tools.ExportEnvironmentWithEnvman("FASTLANE_SESSION", fs); err != nil { + failf("Failed to export FASTLANE_SESSION, error: %s", err) + } + + if err := os.Setenv("FASTLANE_SESSION", fs); err != nil { + failf("Failed to set FASTLANE_SESSION env, error: %s", err) + } + + log.Donef("Session exported") + } + // Split lane option laneOptions, err := shellquote.Split(configs.Lane) if err != nil { diff --git a/vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/LICENSE b/vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/LICENSE new file mode 100644 index 0000000..a6a5c39 --- /dev/null +++ b/vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Bitrise + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/devportalservice/devportalservice.go b/vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/devportalservice/devportalservice.go new file mode 100644 index 0000000..907207f --- /dev/null +++ b/vendor/github.com/bitrise-io/steps-deploy-to-itunesconnect-deliver/devportalservice/devportalservice.go @@ -0,0 +1,151 @@ +package devportalservice + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "strings" + "text/template" + + "github.com/bitrise-io/go-utils/log" +) + +// portalData ... +type portalData struct { + AppleID string `json:"apple_id"` + Password string `json:"password"` + ConnectionExpiryDate string `json:"connection_expiry_date"` + SessionCookies map[string][]cookie `json:"session_cookies"` +} + +// cookie ... +type cookie struct { + Name string `json:"name"` + Path string `json:"path"` + Value string `json:"value"` + Domain string `json:"domain"` + Secure bool `json:"secure"` + Expires string `json:"expires,omitempty"` + MaxAge int `json:"max_age,omitempty"` + Httponly bool `json:"httponly"` + ForDomain *bool `json:"for_domain,omitempty"` +} + +// SessionData will fetch the session from Bitrise for the connected Apple developer account +// If the BITRISE_PORTAL_DATA_JSON is provided (for debug purposes) it will use that instead. +func SessionData() (string, []error) { + p, err := getDeveloperPortalData(os.Getenv("BITRISE_BUILD_URL"), os.Getenv("BITRISE_BUILD_API_TOKEN")) + if err != nil { + return "", []error{err} + } + + cookies, errors := convertDesCookie(p.SessionCookies["https://idmsa.apple.com"]) + session := strings.Join(cookies, "") + return session, errors +} + +func getDeveloperPortalData(buildURL, buildAPIToken string) (portalData, error) { + var p portalData + + j, exists := os.LookupEnv("BITRISE_PORTAL_DATA_JSON") + if exists && j != "" { + return p, json.Unmarshal([]byte(j), &p) + } + + if buildURL == "" { + return portalData{}, fmt.Errorf("BITRISE_BUILD_URL env is not exported") + } + + if buildAPIToken == "" { + return portalData{}, fmt.Errorf("BITRISE_BUILD_API_TOKEN env is not exported") + } + + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/apple_developer_portal_data.json", buildURL), nil) + if err != nil { + return portalData{}, err + } + + req.Header.Add("BUILD_API_TOKEN", buildAPIToken) + + if _, err := performRequest(req, &p); err != nil { + return portalData{}, fmt.Errorf("Falied to fetch portal data from Bitrise, error: %s", err) + } + return p, nil +} + +func convertDesCookie(cookies []cookie) ([]string, []error) { + var convertedCookies []string + var errors []error + for _, c := range cookies { + if convertedCookies == nil { + convertedCookies = append(convertedCookies, "---"+"\n") + } + + if c.ForDomain == nil { + b := true + c.ForDomain = &b + } + + tmpl, err := template.New("").Parse(`- !ruby/object:HTTP::Cookie + name: {{.Name}} + value: {{.Value}} + domain: {{.Domain}} + for_domain: {{.ForDomain}} + path: "{{.Path}}" +`) + if err != nil { + errors = append(errors, fmt.Errorf("Failed to create golang template for the cookie: %v", c)) + continue + } + + var b bytes.Buffer + err = tmpl.Execute(&b, c) + if err != nil { + errors = append(errors, fmt.Errorf("Failed to parse cookie: %v", c)) + continue + } + + convertedCookies = append(convertedCookies, b.String()+"\n") + } + + return convertedCookies, errors +} + +func performRequest(req *http.Request, requestResponse interface{}) ([]byte, error) { + client := http.Client{} + response, err := client.Do(req) + if err != nil { + // On error, any Response can be ignored + return nil, fmt.Errorf("failed to perform request, error: %s", err) + } + + // The client must close the response body when finished with it + defer func() { + if cerr := response.Body.Close(); cerr != nil { + log.Warnf("Failed to close response body, error: %s", cerr) + } + }() + + body, err := ioutil.ReadAll(response.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response body, error: %s", err) + } + + if response.StatusCode != http.StatusOK { + return nil, fmt.Errorf("Response status: %d - Body: %s", response.StatusCode, string(body)) + } + + // Parse JSON body + if requestResponse != nil { + if err := json.Unmarshal([]byte(body), &requestResponse); err != nil { + return nil, fmt.Errorf("failed to unmarshal response (%s), error: %s", body, err) + } + } + return body, nil +} + +func main() { +} diff --git a/vendor/github.com/bitrise-tools/go-steputils/tools/tools.go b/vendor/github.com/bitrise-tools/go-steputils/tools/tools.go new file mode 100644 index 0000000..3372b16 --- /dev/null +++ b/vendor/github.com/bitrise-tools/go-steputils/tools/tools.go @@ -0,0 +1,14 @@ +package tools + +import ( + "strings" + + "github.com/bitrise-io/go-utils/command" +) + +// ExportEnvironmentWithEnvman ... +func ExportEnvironmentWithEnvman(key, value string) error { + cmd := command.New("envman", "add", "--key", key) + cmd.SetStdin(strings.NewReader(value)) + return cmd.Run() +}