Added parent hook and some renderer #1
No reviewers
Labels
No Label
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Bitmessage/buildbot_multibuild#1
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "Ss_singh/buildbot_multibuild:hooks"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closed it by mistake. Expecting reviews.
lib/wine.py
should be renamed, maybe something likerenderers.py
@ -14,1 +14,4 @@
from os.path import exists, isfile, join, listdir
import requests
request_url = "https://buildbot.sysdeploy.org/change_hook/base"
The hostname part of the
request_url
should be dynamic. However since it doesn't depend on a specific job, it doesn't need to use interpolate.What's the hostname part again?
https://git.bitmessage.org/Bitmessage/buildbot-config/src/branch/master/master.cfg#L1435
You said it should be dynamic, where should this come from then?
Something like
the
buildbotURL
could be passed as an argument totrigger_child_hooks
.@ -15,0 +20,4 @@
'Accept': 'text/plain'
}
request_data = {
'repository': 'git@git.bitmessage.org:Sysdeploy/buildbot-scripts.git',
this should be extracted from the current properties.
You mean it should come from
util.Property("repository")
? Do I need to save this repo url in some property?Like,
property="repo_url"
in buildFactory step and use that later when executing the multibuild.py script?Yes.
You should pass it as it is. Similar with "branch". I don't think others need passing.
If I understand you correctly, yes. These two properties you're basically just proxying from the parent to the child. But you're also adding more properties, mainly "jobname" and "dockerfile".
@ -15,0 +26,4 @@
'comments': 'testcomment',
}
ty = 'child_hook'
this is fixed, derived from the base hook class.
Since we don't need
type
, I'd just remove itWe still need to construct the full URL, which consists of the URL of the buildbot server and the path for the base webhook. The latter part is statoc, I don't even think it's configurable in buildbot, it's derived from the hook class.
So what this 'base webhook' should actually be?
I think it's fixed at
/change_hook/base
@ -15,0 +27,4 @@
}
ty = 'child_hook'
hn = 'buildbot.sysdeploy.org' #hostname here(required?)
this can be extracted from global variables
Similarly we don't need
node
here so it can be removedyes
@ -40,0 +72,4 @@
addn = addn.format(build_script_available=build_script_exists, test_script_available=test_script_exists)
# make a post request
request_data['properties'] = '{"node":{hn},"type":{ty}{addn}"}'.format(hn=hn, ty=ty, addn=addn)
node
andtype
we don't need, that's for sysdeploy. we should put all the properties (build_script_available, test_script_available, dockerfile, ...) into this dict, there shouldn't be a sub-dict.I think it would look something like this (still may need fine tuning):
Can I access this
Util
in multibuid.py as well? I just passed the 'repository' and 'branch' as command line args while executing multibuild.pymultibuild.py
will have to be loaded from the buildbot config, just like now it's importinglib/wine.py
, for example. But it can be made into a separate pip module, for example, so it can be developed and used independently.@ -40,0 +73,4 @@
# make a post request
request_data['properties'] = '{"node":{hn},"type":{ty}{addn}"}'.format(hn=hn, ty=ty, addn=addn)
requests.post(request_url, headers=request_headers, data=request_data)
we also need to add the repo information, i.e. the pre-existing properties.
And those are what? 'repository', 'branch', 'author', these things?
yes. I think for an MVP we only need
repository
andbranch
, mayberevision
. For later, probablyowner
andowners
(the way I have it setup now, it would allow people to re-run jobs for their own PRs manually, without these two only admin can re-run job). I don't thinkauthor
is needed, that's just something I borrowed from somewhere else.@ -0,0 +44,4 @@
name="Execute build script",
command=[
"bash",
util.Interpolate(".buildbot/$(prop:jobname)/build.sh"),
typo (I forgot the correct syntax but at the very least
s
is missing after)
)Got it. It should be
%(prop:<propname>)s
@ -0,0 +61,4 @@
)
)
# execute multibuild.py
this will be a separate
BuildFactory
. There will be a child one (what you have above), and a parent one (what you have below)I've made a few changes
@ -0,0 +26,4 @@
@util.renderer
def isnt_gitea(props):
return not _is_gitea(props)
the "old" renderers (above) I would leave out of here and just keep them in the config repo. They aren't really related to this project.
the ones below can stay.
But we need to check if its github or gitea, don't we?
Yes but we don't need to do this in this project. The
master.cfg
would look something like this:But see, it still need those functions
Ah wait, which
master.cfg
you mean here? The one in buildbot-config repo? Or you mean that hook here should be renamed tomaster.cfg
?This repo is a kind of plugin, or module. It's not a full configuration for a buildbot instance. For deployment, you edit the instance configuration and include this module.
Created a PR addressing this in the buildbot-config repo
@ -40,0 +65,4 @@
test_script_exists = True
# make a post request
request_data['dockerfile'] = open(join(directory, job, "Dockerfile"), "r").read()
There should be additional code for modifying the dockerfile. At the very least, it needs to install buildbot-worker and its dependencies, setup the default worker and run it in entrypoint. At the moment we can assume "apt", but in the future it should be able to detect the distro and adjust commands based on that.
For security it should also filter the file to remove CMD or ENTRYFILE lines.
Okay it's like take the contents of already available Dockerfile and append it with extra commands based on the distro.
Yes something like that, but it should be only the buildbot-specific stuff and not the whole existing
Dockerfile
I've pushed an update resolving this. Kindly have a look
@ -40,0 +70,4 @@
request_data['test_script_available'] = str(test_script_exists)
requests.post(request_url, headers=request_headers, data=request_data)
if __name__ == "__main__":
I realised a problem. The code needs to be split between master and worker parts. Master code doesn't see the directories and files, and worker code doesn't have access to properties.
So my suggestion would be to add a
BuildStep
that constructs a JSON string (i.e. a renderer) and uploads it into the worker as a file. The next step will instruct the worker to run a script that will fetch the props from this JSON files, combines them with the per-job props and calls the child hooks.@ -0,0 +15,4 @@
gitea_privkey = util.Secret('gitea_privkey')
travis_bash = util.BuildFactory()
travis_bash.addStep(
I think something more like the
brew_package_steps
from the config repo. One for adding steps for the parentBuildFactory
, one for the children.Then we can just have an example file to show how to use it, instead of a full buildbot config needing to reside in this repo.
Not bad
@ -15,0 +37,4 @@
USER buildbot
ENTRYPOINT /entrypoint.sh "$BUILDMASTER" "$WORKERNAME" "$WORKERPASS"
should be the same as for
bionic
(different path, missing wget)Also I have a pending PR for adding multistage builds in buildbot: https://github.com/buildbot/buildbot/pull/6314
This way we can have all of this in just one Dockerfile stub, just in different stagesand use build arguments to pass the distro docker in realtime.
It would then look something like this:
@ -40,0 +93,4 @@
with open(path, "r") as file:
contents = file.read()
# remove any line containing CMD or ENTRYFILE keywords
contents = re.sub(r"(?m)^CMD.*$", "", contents)
How about just
@ -40,0 +96,4 @@
contents = re.sub(r"(?m)^CMD.*$", "", contents)
contents = re.sub(r"(?m)^ENTRYFILE.*$", "", contents)
return contents + eval("dockerfile_extra_contents_" + os_codename)
No
eval
, it's evil. Maybe use a dict, or just try the multistage.@ -40,0 +115,4 @@
test_script_exists = True
# make a post request
request_data["dockerfile"] = get_dockerfile_contents(
I think it should be
@ -40,0 +120,4 @@
)
request_data["build_script_available"] = str(build_script_exists)
request_data["test_script_available"] = str(test_script_exists)
requests.post(request_url, headers=request_headers, data=request_data)
proxied properties are missing
I think they are still missing. Like
repository
andbranch
.Well, they were already being added before the hook function was getting triggered but anyways, now I've them placed altogether.
@ -40,0 +156,4 @@
Add a step to the build factory
"""
build_factory.addStep(
steps.ShellCommand(
should also have conditionals for
build_script_exists
. If it doesn't, this step is skipped and hidden.@ -40,0 +158,4 @@
build_factory.addStep(
steps.ShellCommand(
name="build_" + job,
command=["bash", "-c", "cd " + join(directory, job) + " && ./build.sh"],
I wouldn't change the directory, but just run it from it, i.e.
@ -40,0 +168,4 @@
Add a step to the build factory
"""
build_factory.addStep(
steps.ShellCommand(
analogous changes as with
build.sh
@ -0,0 +5,4 @@
@util.renderer
def is_build_script_available(props):
# Actual check will got here
return props.getProperty("jobname", default="") != ""
should check for the correct property
@ -0,0 +16,4 @@
@util.renderer
def is_test_script_available(props):
# Actual check will got here
return props.getProperty("jobname", default="") != ""
should also check the correct property
We also need some way to construct the worker environment for the parent job
(such as a Dockerfile). Currently
multibuild.py
won't be on the workerrunning the parent job, so it won't run.
@ -40,0 +129,4 @@
),
"build_script_available": is_build_script_available(build_script_exists),
"test_script_available": is_test_script_available(test_script_exists),
"repository": repository,
I think
repository
andbranch
are a level higher.@ -40,0 +159,4 @@
branch,
"https://buildbot.bitmessage.org",
util.Interpolate("%(prop:os_codename)s"),
],
For now it's probably ok. Over longer term however the
os_codename
isn't extracted from the parent (parent may be running something else than the child should), but from the childDockerfile
. TheDockerfile
will begin with something likeFROM ubuntu:bionic AS ...
, so that determines the OS.@ -40,0 +164,4 @@
)
def add_child_build_sh_step(build_factory, job, directory=".buildbot"):
I'm not 100% sure this will pass properties. A safer solution would be to create a child of
ShellCommand
and callsuper
with a constructedcommand
.@ -0,0 +1,83 @@
#!/usr/bin/env python3
I think we can remove this file.
WIP: Added parent hook and some rendererto Added parent hook and some renderer