def application_images_build_submit(application_id): application = Application.query.filter_by(id=application_id).first() if application is None: abort(404) project = application.project organization = application.project.organization form = ImageBuildSubmitForm() form.application_id.choices = [ (str(application.id), f'{organization.slug}/{project.slug}: {application.slug}') ] form.application_id.data = str(application.id) if form.validate_on_submit(): organization_slug = organization.slug project_slug = project.slug application_slug = application.slug repository_name = f"cabotage/{organization_slug}/{project_slug}/{application_slug}" fileobj = request.files['build_file'] if fileobj: minio_response = minio.write_object(organization_slug, project_slug, application_slug, fileobj) image = Image( application_id=application.id, repository_name=repository_name, build_slug=minio_response['path'], ) db.session.add(image) db.session.flush() activity = Activity(verb='submit', object=image, data={ 'user_id': str(current_user.id), 'timestamp': datetime.datetime.utcnow().isoformat(), }) db.session.add(activity) db.session.commit() run_image_build.delay(image_id=image.id) return redirect( url_for('user.project_application', org_slug=organization.slug, project_slug=project.slug, app_slug=application.slug)) return render_template('user/application_images_build_submit.html', form=form, application=application)
def process_deployment_hook(hook): installation_id = hook.payload['installation']['id'] deployment = hook.payload['deployment'] environment = deployment['environment'] repository = hook.payload['repository'] sender = hook.payload['sender'] bearer_token = github_app.bearer_token access_token = None try: slugs = environment.split('/') if len(slugs) != 2 or slugs[0] != 'cabotage': print('not configured for this environment') return False _, application_id = slugs application = Application.query.filter_by(id=application_id).first() if application is None: print('could not find application') return False if application.github_app_installation_id != installation_id: print('application not configured with installation id') return False access_token_response = requests.post( f'https://api.github.com/installations/{installation_id}/access_tokens', headers={ 'Accept': 'application/vnd.github.machine-man-preview+json', 'Authorization': f'Bearer {bearer_token}', }) if 'token' not in access_token_response.json(): print(f'Unable to authenticate for {installation_id}') print(access_token_response.json()) raise HookError(f'Unable to authenticate for {installation_id}') access_token = access_token_response.json() post_deployment_status_update(access_token["token"], deployment['statuses_url'], 'pending', 'Deployment is starting!') tarball_request = requests.get( f'https://api.github.com/repos/{repository["full_name"]}/tarball/{deployment["sha"]}', headers={ 'Accept': 'application/vnd.github.machine-man-preview+json', 'Authorization': f'token {access_token["token"]}', }, stream=True, ) github_tarball_fd, github_tarball_path = tempfile.mkstemp() release_tarball_fd, release_tarball_path = tempfile.mkstemp() try: print('rewriting tarfile... for reasons') with open(github_tarball_path, 'wb') as handle: for chunk in tarball_request.iter_content(4096): handle.write(chunk) with tarfile.open(github_tarball_path, 'r') as github_tarfile: with tarfile.open(release_tarball_path, 'w|gz') as release_tarfile: for member in github_tarfile: tar_info = member tar_info.name = f'./{str(Path(*Path(member.name).parts[1:]))}' release_tarfile.addfile( tar_info, github_tarfile.extractfile(member)) print('uploading tar to minio') with open(release_tarball_path, 'rb') as handle: minio_response = minio.write_object( application.project.organization.slug, application.project.slug, application.slug, handle) print(f'uploaded tar to {minio_response["path"]}') finally: os.remove(github_tarball_path) os.remove(release_tarball_path) image = Image( application_id=application.id, repository_name= f"cabotage/{application.project.organization.slug}/{application.project.slug}/{application.slug}", build_slug=minio_response['path'], image_metadata={ **deployment, 'installation_id': installation_id, 'auto_deploy': True }, ) db.session.add(image) db.session.flush() activity = Activity(verb='submit', object=image, data={ 'sender': sender, 'timestamp': datetime.datetime.utcnow().isoformat(), }) db.session.add(activity) db.session.commit() run_image_build.delay(image_id=image.id) post_deployment_status_update( access_token["token"], deployment['statuses_url'], 'pending', 'Code retrieved! Image build commencing.') return True except HookError as exc: if access_token and 'token' in access_token: post_deployment_status_update(access_token["token"], deployment['statuses_url'], 'error', str(exc))