Skip to content

Commit d352f32

Browse files
committed
Merge pull request #1026 from alphagov/pipeline_ordering
Order create-cloudfoundry pipeline first in concourse.
2 parents 74ae3fe + a2e6493 commit d352f32

File tree

3 files changed

+227
-0
lines changed

3 files changed

+227
-0
lines changed

concourse/scripts/pipelines-cloudfoundry.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ update_pipeline() {
185185
case $pipeline_name in
186186
create-cloudfoundry)
187187
upload_pipeline
188+
"${SCRIPT_DIR}/set_pipeline_ordering.rb" "${pipeline_name}"
189+
echo "ordered '${pipeline_name}' pipeline first"
188190
;;
189191
deployment-kick-off)
190192
if [ "${ENABLE_MORNING_DEPLOYMENT:-}" = "true" ]; then
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'net/http'
4+
require 'yaml'
5+
require 'json'
6+
7+
if ARGV.length != 1
8+
abort <<-EOT
9+
Usage:
10+
11+
#{$0} <pipeline_order>
12+
13+
Being:
14+
15+
pipeline_order comma-separated list of pipeline names
16+
17+
EOT
18+
end
19+
pipelines = ARGV[0].split(",")
20+
21+
if ENV["FLY_TARGET"].nil? || ENV["FLY_TARGET"].empty?
22+
abort "FLY_TARGET not set"
23+
end
24+
flyrc = YAML.load_file("#{ENV['HOME']}/.flyrc")
25+
if flyrc.fetch("targets")[ENV['FLY_TARGET']].nil?
26+
abort "Target '#{ENV['FLY_TARGET']}' not found in .flyrc. Use the fly command to set this target up before using this script"
27+
end
28+
concourse_url = flyrc.fetch("targets").fetch(ENV['FLY_TARGET']).fetch('api')
29+
bearer_token = flyrc.fetch("targets").fetch(ENV['FLY_TARGET']).fetch('token').fetch('value')
30+
31+
uri = URI.parse("#{concourse_url}/api/v1/teams/main/pipelines/ordering")
32+
req = Net::HTTP::Put.new(uri.request_uri)
33+
34+
req["Authorization"] = "Bearer #{bearer_token}"
35+
36+
req.content_type = "application/json"
37+
req.body = JSON.dump(pipelines)
38+
39+
resp = nil
40+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
41+
resp = http.request(req)
42+
end
43+
44+
unless resp.code.to_i == 200
45+
abort "Non-200 response '#{resp.code}' from concourse\n#{resp.body}"
46+
end
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package scripts_test
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
7+
"os/exec"
8+
"strings"
9+
10+
. "github.com/onsi/ginkgo"
11+
. "github.com/onsi/gomega"
12+
"github.com/onsi/gomega/gbytes"
13+
"github.com/onsi/gomega/gexec"
14+
"github.com/onsi/gomega/ghttp"
15+
)
16+
17+
var _ = Describe("set_pipeline_ordering", func() {
18+
const (
19+
flyrcTarget = `unit-test`
20+
bearerToken = `2d5ebf5efbac7997025e9364f0319304ce89480724077d5f7103c234460e8d0de928f884553686aa30afc9629278b9595059d0e0be41ff5ffc5cf3a04f67e57f`
21+
)
22+
23+
var (
24+
concourse *ghttp.Server
25+
tmpHome string
26+
)
27+
28+
BeforeEach(func() {
29+
var err error
30+
concourse = ghttp.NewServer()
31+
tmpHome, err = ioutil.TempDir("", "tmphome")
32+
Expect(err).NotTo(HaveOccurred())
33+
})
34+
AfterEach(func() {
35+
concourse.Close()
36+
os.RemoveAll(tmpHome)
37+
})
38+
39+
It("makes the request to concourse", func() {
40+
concourse.AppendHandlers(ghttp.CombineHandlers(
41+
ghttp.VerifyRequest("PUT", "/api/v1/teams/main/pipelines/ordering"),
42+
ghttp.VerifyHeaderKV("Authorization", "Bearer "+bearerToken),
43+
ghttp.VerifyJSON(`["pipeline-one","pipeline-two"]`),
44+
ghttp.RespondWith(200, ""),
45+
))
46+
47+
populateFlyrc(tmpHome, flyrcTarget, concourse.URL(), bearerToken)
48+
49+
cmd := exec.Command("./set_pipeline_ordering.rb", "pipeline-one,pipeline-two")
50+
cmd.Env = mergeEnvLists(
51+
[]string{"HOME=" + tmpHome, "FLY_TARGET=" + flyrcTarget},
52+
os.Environ(),
53+
)
54+
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
55+
Expect(err).NotTo(HaveOccurred())
56+
Eventually(session, 1).Should(gexec.Exit(0))
57+
58+
Expect(concourse.ReceivedRequests()).To(HaveLen(1))
59+
})
60+
61+
It("errors if no pipelines given on cmdline", func() {
62+
cmd := exec.Command("./set_pipeline_ordering.rb")
63+
cmd.Env = mergeEnvLists(
64+
[]string{"HOME=" + tmpHome, "FLY_TARGET=" + flyrcTarget},
65+
os.Environ(),
66+
)
67+
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
68+
Expect(err).NotTo(HaveOccurred())
69+
Eventually(session, 1).Should(gexec.Exit(1))
70+
Expect(session.Err).To(gbytes.Say("Usage:"))
71+
72+
Expect(concourse.ReceivedRequests()).To(HaveLen(0))
73+
})
74+
75+
It("errors if FLY_TARGET isn't set", func() {
76+
cmd := exec.Command("./set_pipeline_ordering.rb", "pipeline-one,pipeline-two")
77+
cmd.Env = mergeEnvLists(
78+
[]string{"HOME=" + tmpHome},
79+
os.Environ(),
80+
)
81+
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
82+
Expect(err).NotTo(HaveOccurred())
83+
Eventually(session, 1).Should(gexec.Exit(1))
84+
85+
Expect(concourse.ReceivedRequests()).To(HaveLen(0))
86+
87+
cmd = exec.Command("./set_pipeline_ordering.rb", "pipeline-one,pipeline-two")
88+
cmd.Env = mergeEnvLists(
89+
[]string{"HOME=" + tmpHome, "FLY_TARGET="},
90+
os.Environ(),
91+
)
92+
session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
93+
Expect(err).NotTo(HaveOccurred())
94+
Eventually(session, 1).Should(gexec.Exit(1))
95+
96+
Expect(concourse.ReceivedRequests()).To(HaveLen(0))
97+
})
98+
99+
It("errors if FLY_TARGET doesn't exist in flyrc", func() {
100+
populateFlyrc(tmpHome, flyrcTarget, concourse.URL(), bearerToken)
101+
102+
cmd := exec.Command("./set_pipeline_ordering.rb", "pipeline-one,pipeline-two")
103+
cmd.Env = mergeEnvLists(
104+
[]string{"HOME=" + tmpHome, "FLY_TARGET=different-target"},
105+
os.Environ(),
106+
)
107+
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
108+
Expect(err).NotTo(HaveOccurred())
109+
Eventually(session, 1).Should(gexec.Exit(1))
110+
Expect(session.Err).To(gbytes.Say("Target 'different-target' not found in .flyrc"))
111+
112+
Expect(concourse.ReceivedRequests()).To(HaveLen(0))
113+
})
114+
115+
It("errors if concourse returns non-200 response", func() {
116+
concourse.AppendHandlers(ghttp.RespondWith(401, "unauthorized"))
117+
118+
populateFlyrc(tmpHome, flyrcTarget, concourse.URL(), bearerToken)
119+
120+
cmd := exec.Command("./set_pipeline_ordering.rb", "pipeline-one,pipeline-two")
121+
cmd.Env = mergeEnvLists(
122+
[]string{"HOME=" + tmpHome, "FLY_TARGET=" + flyrcTarget},
123+
os.Environ(),
124+
)
125+
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
126+
Expect(err).NotTo(HaveOccurred())
127+
Eventually(session, 1).Should(gexec.Exit(1))
128+
Expect(session.Err).To(gbytes.Say("Non-200 response '401'"))
129+
130+
Expect(concourse.ReceivedRequests()).To(HaveLen(1))
131+
})
132+
})
133+
134+
// MergeEnvLists merges the two environment lists such that
135+
// variables with the same name in "in" replace those in "out".
136+
// This always returns a newly allocated slice.
137+
//
138+
// Lifted from src/cmd/go/internal/base/env.go in the go source tree.
139+
//
140+
// FIXME: When we upgrade to Go 1.9, this can be removed and replaced with a
141+
// simple `cmd.Env := append(os.Environ(), "FOO=bar")` because Go 1.9 de-dups
142+
// the list (https://golang.org/doc/go1.9#os/exec).
143+
func mergeEnvLists(in, out []string) []string {
144+
out = append([]string(nil), out...)
145+
NextVar:
146+
for _, inkv := range in {
147+
k := strings.SplitAfterN(inkv, "=", 2)[0]
148+
for i, outkv := range out {
149+
if strings.HasPrefix(outkv, k) {
150+
out[i] = inkv
151+
continue NextVar
152+
}
153+
}
154+
out = append(out, inkv)
155+
}
156+
return out
157+
}
158+
159+
func populateFlyrc(homedir, target, url, token string) {
160+
filePath := homedir + "/.flyrc"
161+
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0755)
162+
ExpectWithOffset(1, err).NotTo(HaveOccurred())
163+
_, err = fmt.Fprintf(
164+
file,
165+
"targets:\n"+
166+
" %s:\n"+
167+
" api: %s\n"+
168+
" team: main\n"+
169+
" token:\n"+
170+
" type: Bearer\n"+
171+
" value: %s\n",
172+
target,
173+
url,
174+
token,
175+
)
176+
ExpectWithOffset(1, err).NotTo(HaveOccurred())
177+
err = file.Close()
178+
ExpectWithOffset(1, err).NotTo(HaveOccurred())
179+
}

0 commit comments

Comments
 (0)