Added parent hook and some renderer #1

Merged
PeterSurda merged 7 commits from Ss_singh/buildbot_multibuild:hooks into master 2021-12-26 09:05:49 +01:00
Showing only changes of commit 9a55687ec6 - Show all commits

View File

@ -14,18 +14,19 @@ from os import walk
from os.path import exists, isfile, join, listdir from os.path import exists, isfile, join, listdir
import requests import requests
import re import re
from buildbot.plugins import steps, util
ty = '/change_hook/base' ty = "/change_hook/base"
request_headers = { request_headers = {
'Content-Type': 'application/x-www-form-urlencoded', "Content-Type": "application/x-www-form-urlencoded",
'Accept': 'text/plain' "Accept": "text/plain",
} }
request_data = { request_data = {
'project': 'testproject', "project": "testproject",
'comments': 'testcomment', "comments": "testcomment",
} }
dockerfile_extra_contents_focal = ''' dockerfile_extra_contents_focal = """
# Buildbot # Buildbot
RUN apt-get install -yq --no-install-suggests --no-install-recommends \ RUN apt-get install -yq --no-install-suggests --no-install-recommends \
@ -38,9 +39,9 @@ USER buildbot
ENTRYPOINT /entrypoint.sh "$BUILDMASTER" "$WORKERNAME" "$WORKERPASS" ENTRYPOINT /entrypoint.sh "$BUILDMASTER" "$WORKERNAME" "$WORKERPASS"
''' """
dockerfile_extra_contents_bionic = ''' dockerfile_extra_contents_bionic = """
# Buildbot # Buildbot
RUN apt-get install -yq --no-install-suggests --no-install-recommends \ RUN apt-get install -yq --no-install-suggests --no-install-recommends \
@ -57,7 +58,8 @@ USER buildbot
ENTRYPOINT /usr/local/bin/buildbot_entrypoint.sh "$BUILDMASTER" "$WORKERNAME" "$WORKERPASS" ENTRYPOINT /usr/local/bin/buildbot_entrypoint.sh "$BUILDMASTER" "$WORKERNAME" "$WORKERPASS"
''' """
def list_jobs(directory=".buildbot"): def list_jobs(directory=".buildbot"):
""" """
@ -65,10 +67,10 @@ def list_jobs(directory=".buildbot"):
""" """
results = [] results = []
for _ in next(walk(directory))[1]: for _ in next(walk(directory))[1]:
if exists(join(directory, _, "Dockerfile")) \ if exists(join(directory, _, "Dockerfile")) and (
and (exists(join(directory, _, "build.sh")) exists(join(directory, _, "build.sh"))
or exists(join(directory, _, "test.sh")) or exists(join(directory, _, "test.sh"))
): ):
results.append(_) results.append(_)
return results return results
@ -83,21 +85,23 @@ def find_artifacts(directory="out"):
continue continue
return join(directory, _) return join(directory, _)
def get_dockerfile_contents(path, os_codename): def get_dockerfile_contents(path, os_codename):
''' """
Read contents of a Dockerfile and add extra contents for the given os_codename Read contents of a Dockerfile and add extra contents for the given os_codename
''' """
with open(path, 'r') as file: with open(path, "r") as file:
contents = file.read() contents = file.read()
# remove any line containing CMD or ENTRYFILE keywords # remove any line containing CMD or ENTRYFILE keywords
contents = re.sub(r'(?m)^CMD.*$', '', contents) contents = re.sub(r"(?m)^CMD.*$", "", contents)
Ss_singh marked this conversation as resolved
Review

How about just

contents = re.sub(r"(?m)^(CMD|ENTRYFILE).*$", "", contents)
How about just ``` contents = re.sub(r"(?m)^(CMD|ENTRYFILE).*$", "", contents) ```
contents = re.sub(r'(?m)^ENTRYFILE.*$', '', contents) contents = re.sub(r"(?m)^ENTRYFILE.*$", "", contents)
return contents + eval("dockerfile_extra_contents_" + os_codename) return contents + eval("dockerfile_extra_contents_" + os_codename)
def trigger_child_hooks(buildbotUrl:str, os_codename:str, directory=".buildbot"):
def trigger_child_hooks(buildbotUrl: str, os_codename: str, directory=".buildbot"):
request_url = buildbotUrl + ty request_url = buildbotUrl + ty
# List all jobs in the directory # List all jobs in the directory
jobs = list_jobs(directory) jobs = list_jobs(directory)
@ -109,16 +113,72 @@ def trigger_child_hooks(buildbotUrl:str, os_codename:str, directory=".buildbot")
build_script_exists = True build_script_exists = True
if exists(join(directory, job, "test.sh")): if exists(join(directory, job, "test.sh")):
test_script_exists = True test_script_exists = True
# make a post request # make a post request
request_data['dockerfile'] = get_dockerfile_contents(join(directory, job, "Dockerfile"), os_codename) request_data["dockerfile"] = get_dockerfile_contents(
request_data['build_script_available'] = str(build_script_exists) join(directory, job, "Dockerfile"), os_codename
request_data['test_script_available'] = str(test_script_exists) )
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) requests.post(request_url, headers=request_headers, data=request_data)
Ss_singh marked this conversation as resolved
Review

proxied properties are missing

proxied properties are missing
Review

I think they are still missing. Like repository and branch.

I think they are still missing. Like `repository` and `branch`.
Review

Well, they were already being added before the hook function was getting triggered but anyways, now I've them placed altogether.

Well, they were already being added before the hook function was getting triggered but anyways, now I've them placed altogether.
def add_parent_step(build_factory, jobname, repository, branch):
"""
Add a step to the parent build factory that will trigger the child hooks
"""
build_factory.addStep(
steps.SetPropertyFromCommand(
name="Get OS codename",
Review

I think repository and branch are a level higher.

I think `repository` and `branch` are a level higher.
command="grep ^VERSION_CODENAME= /etc/os-release | cut -d= -f2",
property="os_codename",
)
)
build_factory.addStep(
steps.ShellCommand(
name="Execute multibuild script",
command=[
"python",
"multibuild.py",
jobname,
repository,
branch,
"https://buildbot.bitmessage.org",
util.Interpolate("%(prop:os_codename)s"),
],
)
)
def add_child_build_sh_step(build_factory, job, directory=".buildbot"):
"""
Add a step to the build factory
"""
build_factory.addStep(
steps.ShellCommand(
Ss_singh marked this conversation as resolved
Review

should also have conditionals for build_script_exists. If it doesn't, this step is skipped and hidden.

should also have conditionals for `build_script_exists`. If it doesn't, this step is skipped and hidden.
name="build_" + job,
command=["bash", "-c", "cd " + join(directory, job) + " && ./build.sh"],
Ss_singh marked this conversation as resolved
Review

I wouldn't change the directory, but just run it from it, i.e.

command=["bash", "-c", join(directory, job, "build.sh")],
I wouldn't change the directory, but just run it from it, i.e. ``` command=["bash", "-c", join(directory, job, "build.sh")],
)
Review

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 child Dockerfile. The Dockerfile will begin with something like FROM ubuntu:bionic AS ..., so that determines the OS.

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 child `Dockerfile`. The `Dockerfile` will begin with something like `FROM ubuntu:bionic AS ...`, so that determines the OS.
)
def add_child_test_sh_step(build_factory, job, directory=".buildbot"):
"""
Review

I'm not 100% sure this will pass properties. A safer solution would be to create a child of ShellCommand and call super with a constructed command.

I'm not 100% sure this will pass properties. A safer solution would be to create a child of `ShellCommand` and call `super` with a constructed `command`.
Add a step to the build factory
"""
build_factory.addStep(
steps.ShellCommand(
name="test_" + job,
command=["bash", "-c", "cd " + join(directory, job) + " && ./test.sh"],
)
)
if __name__ == "__main__": if __name__ == "__main__":
# expect jobname, repository, branch, buildbotUrl, os_codename from command line args # expect jobname, repository, branch, buildbotUrl, os_codename from command line args
import sys import sys
if len(sys.argv) == 6: if len(sys.argv) == 6:
jobname = sys.argv[1] jobname = sys.argv[1]
repository = sys.argv[2] repository = sys.argv[2]
@ -127,10 +187,12 @@ if __name__ == "__main__":
os_codename = sys.argv[5] os_codename = sys.argv[5]
# add these into the request_data # add these into the request_data
request_data['jobname'] = jobname request_data["jobname"] = jobname
request_data['repository'] = repository request_data["repository"] = repository
request_data['branch'] = branch request_data["branch"] = branch
trigger_child_hooks(buildbotUrl, os_codename) trigger_child_hooks(buildbotUrl, os_codename)
else: else:
print("Usage: python3 multibuild.py <jobname> <repository> <branch> <buildbotUrl> <os_codename>") print(
"Usage: python3 multibuild.py <jobname> <repository> <branch> <buildbotUrl> <os_codename>"
)