grim/convey
Clone
Summary
Browse
Changes
Graph
Change all the copyright headers to not use /* */ comments and add some package comments
2018-01-12, Gary Kramlich
d4f80bb35ed0
Change all the copyright headers to not use /* */ comments and add some package comments
// Convey
// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package
bitbucket
import
(
"fmt"
"os"
"path/filepath"
"strings"
"github.com/kballard/go-shellquote"
"bitbucket.org/rw_grim/convey/config"
"bitbucket.org/rw_grim/convey/docker"
"bitbucket.org/rw_grim/convey/plans"
"bitbucket.org/rw_grim/convey/stages"
"bitbucket.org/rw_grim/convey/state"
"bitbucket.org/rw_grim/convey/tasks"
"github.com/go-yaml/yaml"
)
type
Loader
struct
{}
func
addTask
(
name
string
,
task
tasks
.
Task
,
plan
plans
.
Plan
,
cfg
*
config
.
Config
)
{
cfg
.
Tasks
[
name
]
=
task
plan
.
Stages
[
0
].
Tasks
=
append
(
plan
.
Stages
[
0
].
Tasks
,
name
)
}
func
addScript
(
name
string
,
image
image
,
script
[]
string
,
plan
plans
.
Plan
,
cfg
*
config
.
Config
)
{
task
:=
&
docker
.
Run
{
Shell
:
"/bin/sh"
,
Script
:
script
,
Image
:
image
.
Name
,
WorkDir
:
"/workspace"
,
}
addTask
(
name
,
task
,
plan
,
cfg
)
}
func
addPipeline
(
name
string
,
defImage
image
,
pipelines
[]
pipeline
,
cfg
*
config
.
Config
)
error
{
plan
:=
plans
.
Plan
{
Stages
:
[]
stages
.
Stage
{
stages
.
Stage
{
Name
:
"stage-0"
,
Enabled
:
true
,
Tasks
:
[]
string
{
"import"
},
Run
:
"on-success"
,
},
},
}
for
idx
,
pipeline
:=
range
pipelines
{
loginTask
:=
""
logoutTask
:=
""
image
:=
defImage
if
pipeline
.
Steps
.
Image
.
Name
!=
""
{
image
=
pipeline
.
Steps
.
Image
// if the step has an image with a username, we need to add the tasks to login and logout
if
image
.
Username
!=
""
{
registry
,
_
,
_
:=
docker
.
ParseImage
(
image
.
Name
)
// create and add the login task to the stage
loginTask
=
fmt
.
Sprintf
(
"%s-%d-login"
,
name
,
idx
)
cfg
.
Tasks
[
loginTask
]
=
&
docker
.
Login
{
Username
:
image
.
Username
,
Password
:
image
.
Password
,
Server
:
registry
,
}
// create the logout task, but store the name so we can add it after the other tasks
logoutTask
=
fmt
.
Sprintf
(
"%s-%d-logout"
,
name
,
idx
)
cfg
.
Tasks
[
logoutTask
]
=
&
docker
.
Logout
{
Server
:
registry
,
}
}
}
else
if
image
.
Username
!=
""
{
// if we're using the global image and it has a username, we need to add the tasks to the stage
loginTask
=
"login"
logoutTask
=
"logout"
}
// if we have a login task, add it to the tasks for this stage
if
loginTask
!=
""
{
plan
.
Stages
[
idx
].
Tasks
=
append
(
plan
.
Stages
[
idx
].
Tasks
,
loginTask
)
}
// now figure out how to parse the script in the config
currentScript
:=
[]
string
{}
last
:=
-
1
for
scriptIdx
,
command
:=
range
pipeline
.
Steps
.
Script
{
argv
,
err
:=
shellquote
.
Split
(
command
)
if
err
!=
nil
{
return
err
}
if
len
(
argv
)
>
0
{
if
strings
.
TrimSpace
(
strings
.
ToLower
(
argv
[
0
]))
==
"docker"
{
taskName
:=
fmt
.
Sprintf
(
"%s-step-%d-%d"
,
name
,
idx
,
scriptIdx
)
// if we have existing script commands add them now
if
len
(
currentScript
)
>
0
{
taskName
:=
fmt
.
Sprintf
(
"%s-step-%d-%d"
,
name
,
idx
,
scriptIdx
-
1
)
addScript
(
taskName
,
image
,
currentScript
,
plan
,
cfg
)
currentScript
=
[]
string
{}
last
=
scriptIdx
}
// now figure out what docker command we're running
task
,
err
:=
parseDockerCommand
(
argv
)
if
err
!=
nil
{
return
err
}
addTask
(
taskName
,
task
,
plan
,
cfg
)
last
=
scriptIdx
}
else
{
currentScript
=
append
(
currentScript
,
command
)
}
}
}
// if we have existing script commands add them now
if
len
(
currentScript
)
>
0
{
name
:=
fmt
.
Sprintf
(
"%s-step-%d-%d"
,
name
,
idx
,
last
+
1
)
addScript
(
name
,
image
,
currentScript
,
plan
,
cfg
)
}
// if we have a logout task, add it to the tasks for this stage
if
logoutTask
!=
""
{
plan
.
Stages
[
idx
].
Tasks
=
append
(
plan
.
Stages
[
idx
].
Tasks
,
logoutTask
)
}
}
cfg
.
Plans
[
name
]
=
plan
return
nil
}
func
addPipelines
(
base
string
,
defImage
image
,
pipelines
map
[
string
][]
pipeline
,
cfg
*
config
.
Config
)
error
{
for
name
,
branchPipeline
:=
range
pipelines
{
if
len
(
branchPipeline
)
>
0
{
name
:=
fmt
.
Sprintf
(
"%s-%s"
,
base
,
name
)
err
:=
addPipeline
(
name
,
defImage
,
branchPipeline
,
cfg
)
if
err
!=
nil
{
return
err
}
}
}
return
nil
}
func
(
l
*
Loader
)
Load
(
base
,
path
string
,
data
[]
byte
,
disableDeprecated
bool
)
(
*
config
.
Config
,
error
)
{
var
pipeline
bitbucketPipelines
err
:=
yaml
.
Unmarshal
(
data
,
&
pipeline
)
if
err
!=
nil
{
return
nil
,
err
}
cfg
:=
&
config
.
Config
{
Tasks
:
map
[
string
]
tasks
.
Task
{
"import"
:
&
docker
.
Import
{
Files
:
[]
string
{
"."
},
},
},
Plans
:
map
[
string
]
plans
.
Plan
{},
}
// store the default image
defImage
:=
pipeline
.
Image
// if the default image has a username, add a login/logout task
if
defImage
.
Username
!=
""
{
registry
,
_
,
_
:=
docker
.
ParseImage
(
defImage
.
Name
)
cfg
.
Tasks
[
"login"
]
=
&
docker
.
Login
{
Username
:
defImage
.
Username
,
Password
:
defImage
.
Password
,
Server
:
registry
,
}
cfg
.
Tasks
[
"logout"
]
=
&
docker
.
Logout
{
Server
:
registry
,
}
}
// add the default pipelines
if
len
(
pipeline
.
Pipelines
.
Default
)
>
0
{
err
=
addPipeline
(
"default"
,
defImage
,
pipeline
.
Pipelines
.
Default
,
cfg
)
if
err
!=
nil
{
return
nil
,
err
}
}
err
=
addPipelines
(
"bookmark"
,
defImage
,
pipeline
.
Pipelines
.
Bookmarks
,
cfg
)
if
err
!=
nil
{
return
nil
,
err
}
err
=
addPipelines
(
"branch"
,
defImage
,
pipeline
.
Pipelines
.
Branches
,
cfg
)
if
err
!=
nil
{
return
nil
,
err
}
err
=
addPipelines
(
"custom"
,
defImage
,
pipeline
.
Pipelines
.
Custom
,
cfg
)
if
err
!=
nil
{
return
nil
,
err
}
err
=
addPipelines
(
"tag"
,
defImage
,
pipeline
.
Pipelines
.
Tags
,
cfg
)
if
err
!=
nil
{
return
nil
,
err
}
return
cfg
,
nil
}
func
(
l
*
Loader
)
LoadOverride
(
base
,
path
string
,
data
[]
byte
,
cfg
*
config
.
Config
,
disableDeprecated
bool
)
{
return
}
func
(
l
*
Loader
)
Filenames
()
[]
string
{
return
[]
string
{
"bitbucket-pipelines.yml"
}
}
func
(
l
*
Loader
)
OverrideSuffix
()
string
{
return
"-override"
}
func
(
l
*
Loader
)
DefaultPlan
()
string
{
return
"default"
}
func
(
l
*
Loader
)
ResolvePlanName
(
plan
string
,
cfg
*
config
.
Config
,
st
*
state
.
State
)
string
{
if
plan
!=
""
{
// try to shortcut if we can
if
plan
==
"default"
{
return
"default"
}
customPlan
:=
fmt
.
Sprintf
(
"custom-%s"
,
plan
)
if
_
,
found
:=
cfg
.
Plans
[
customPlan
];
found
{
return
customPlan
}
// we couldn't find the plan, so just return it so convey can return
// an error saying it wasn't found.
return
plan
}
// we're in auto discovery mode! woo?
matchMapper
:=
map
[
string
][]
string
{
"branch"
:
[]
string
{},
}
// figure out the we're looking for
if
gitBranch
:=
os
.
Getenv
(
"GIT_BRANCH"
);
gitBranch
!=
""
{
matchMapper
[
"branch"
]
=
append
(
matchMapper
[
"branch"
],
gitBranch
)
}
if
hgBranch
:=
os
.
Getenv
(
"HG_BRANCH"
);
hgBranch
!=
""
{
matchMapper
[
"branch"
]
=
append
(
matchMapper
[
"branch"
],
hgBranch
)
}
if
hgBookmark
:=
os
.
Getenv
(
"HG_BOOKMARK"
);
hgBookmark
!=
""
{
matchMapper
[
"bookmark"
]
=
append
(
matchMapper
[
"bookmark"
],
hgBookmark
)
}
for
name
,
_
:=
range
cfg
.
Plans
{
for
prefix
,
matchers
:=
range
matchMapper
{
for
_
,
matcher
:=
range
matchers
{
calculatedName
:=
fmt
.
Sprintf
(
"%s-%s"
,
prefix
,
matcher
)
fmt
.
Printf
(
"checking %s against %s\n"
,
calculatedName
,
name
)
if
matched
,
_
:=
filepath
.
Match
(
name
,
calculatedName
);
matched
{
return
name
}
}
}
}
return
"default"
}