def execute(self, context): hook = CloudBuildHook(gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain) result = hook.cancel_build( id_=self.id_, project_id=self.project_id, retry=self.retry, timeout=self.timeout, metadata=self.metadata, ) return Build.to_dict(result)
def process_body(self) -> Build: """ Processes the body passed in the constructor :return: the body. :rtype: `google.cloud.devtools.cloudbuild_v1.types.Build` """ if 'source' in self.build: self._verify_source() self._reformat_source() return Build(self.build)
def execute(self, context): hook = CloudBuildHook(gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain) result = hook.run_build_trigger( trigger_id=self.trigger_id, source=self.source, project_id=self.project_id, wait=self.wait, retry=self.retry, timeout=self.timeout, metadata=self.metadata, ) return Build.to_dict(result)
def execute(self, context): hook = CloudBuildHook(gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain) results = hook.list_builds( project_id=self.project_id, location=self.location, page_size=self.page_size, filter_=self.filter_, retry=self.retry, timeout=self.timeout, metadata=self.metadata, ) return [Build.to_dict(result) for result in results]
def execute(self, context): hook = CloudBuildHook(gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain) build = BuildProcessor(build=self.build).process_body() result = hook.create_build( build=build, project_id=self.project_id, wait=self.wait, retry=self.retry, timeout=self.timeout, metadata=self.metadata, ) return Build.to_dict(result)
def main(event, context): """ Triggers a new downstream build based on a PubSub message originating from a parent cloudbuild """ # if cloud build project is not set, exit if not os.getenv('CLOUDBUILD_PROJECT'): logging.warn('Cloud Build project not set') sys.exit(1) # if no data in PubSub event, log and exit if 'data' not in event: logging.info('Unable to find data in PubSub event') sys.exit(1) # decode data in PubSub event data = json.loads(base64.b64decode(event['data']).decode('utf-8')) # if the parent build originated from CF, ignore if data['substitutions'].get('_IS_TRIGGERED_BY_CF', False): logging.warn('Triggered by CF, Ignoring') return logging.info('Parent build not triggered by CF') # if parent build is not a lint build, ignore if 'lint' not in data['tags']: logging.warn('Parent build is not a lint build') return # if parent build has not started, or is in any other state, ignore if data['status'] != 'WORKING': logging.warn('Parent build is not in WORKING status') return logging.info('Parent build is in WORKING status') # if repo ref for the parent build has not enabled PR bot, ignore if data['substitutions']['REPO_NAME'] not in ENABLED_MODULES: logging.warn('Not a supported repo') return if data['substitutions'].get('_DOCKER_TAG_VERSION_DEVELOPER_TOOLS', False): logging.info( f'Found _DOCKER_TAG_VERSION_DEVELOPER_TOOLS. Setting tools image version to {data["substitutions"]["_DOCKER_TAG_VERSION_DEVELOPER_TOOLS"]}' ) CFT_TOOLS_DEFAULT_IMAGE_VERSION = data['substitutions'][ '_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'] # Cloud Build seems to have a bug where if a build is re run through Github UI, it will not set _PR_NUMBER or _HEAD_REPO_URL # workaround using the GH API to infer PR number and _HEAD_REPO_URL PR_NUMBER = data['substitutions'].get('_PR_NUMBER', False) _HEAD_REPO_URL = data['substitutions'].get('_HEAD_REPO_URL', False) # default clone repo step get_repo_args = [ '-c', 'git clone $$REPO_URL && cd $$REPO_NAME && git checkout $$COMMIT_SHA && git status', ] if not (PR_NUMBER or _HEAD_REPO_URL): logging.warn( 'Unable to infer PR number via Cloud Build. Trying via GH API') # get list of github PRs that have this SHA response = requests.get( f'https://api.github.com/search/issues?q={data["substitutions"]["COMMIT_SHA"]}' ) response.raise_for_status() response_obj = response.json() # if more than one PR, ignore if response_obj['total_count'] != 1: logging.info(f'Multiple associated PRs found. Exiting...') return # if only one PR, its safe to assume that is associated with parent build's PR logging.info( f'One associated PR found: {response_obj["items"][0]["number"]}') PR_NUMBER = response_obj['items'][0]['number'] # get target repo URL pr_url = response_obj['items'][0]['html_url'] _HEAD_REPO_URL = pr_url[:pr_url.find('/pull')] # fetch PR at head using PR number get_repo_args = [ '-c', 'git clone $$REPO_URL && cd $$REPO_NAME && git fetch origin pull/$$_PR_NUMBER/head:$$_PR_NUMBER && git checkout $$_PR_NUMBER && git show --name-only', ] # prepare env vars env = [ f'_PR_NUMBER={PR_NUMBER}', f'REPO_NAME={data["substitutions"]["REPO_NAME"]}', f'REPO_URL={_HEAD_REPO_URL}', f'COMMIT_SHA={data["substitutions"]["COMMIT_SHA"]}', ] get_repo_step = BuildStep( name='gcr.io/cloud-builders/git', env=env, args=get_repo_args, id='get_repo', entrypoint='bash', ) # lint comment step lint_args = [ '-c', 'source /usr/local/bin/task_helper_functions.sh && printenv && post_lint_status_pr_comment', ] lint_step = BuildStep( name=f'{CFT_TOOLS_DEFAULT_IMAGE}:{CFT_TOOLS_DEFAULT_IMAGE_VERSION}', env=env, args=lint_args, id='lint_comment', entrypoint='/bin/bash', ) # substitutions sub = { '_IS_TRIGGERED_BY_CF': '1', } # create and trigger build build = Build( steps=[get_repo_step, lint_step], options=BuildOptions(substitution_option='ALLOW_LOOSE'), substitutions=sub, ) response = cloudbuild().create_build(os.getenv('CLOUDBUILD_PROJECT'), build) logging.info(response)
def __init__(self, build: Union[Dict, Build]) -> None: if isinstance(build, Build): self.build = Build(build) self.build = deepcopy(build)