Files

51 lines
2.6 KiB
Python

"""Prepare an independent, pinned checkout and reuse the standard builders."""
import shutil
from app.services.git_service import GitService
from app.services.build_service import BuildService
from app.utils.git_security import git_argv, git_env
from app.utils.system import run_checked
from .plan import PreviewError, relative_file
def prepare(app, preview, target, repo_url):
result = GitService.clone_repository(str(target), repo_url, branch=preview.branch)
if not result.get('success'):
# Raw Git output can contain authenticated repository URLs.
raise PreviewError('Preview repository clone failed. Check repository access and branch.')
sha = preview.commit_sha.lower()
# A PR must name a commit reachable from the selected same-repository branch.
result = run_checked(git_argv('-C', str(target), 'merge-base', '--is-ancestor',
sha, 'HEAD'), timeout=30, env=git_env())
if not result.get('success'):
raise PreviewError('Preview commit is not reachable from the selected repository branch.')
result = run_checked(git_argv('-C', str(target), 'checkout', '--detach', sha),
timeout=60, env=git_env())
if not result.get('success'):
raise PreviewError('Could not check out the requested preview commit.')
# Do not send clone credentials / Git metadata into a Docker build context.
shutil.rmtree(target / '.git')
def build(app, preview, target, image, log_callback=None):
config = dict(BuildService.get_app_build_config(app.id) or {})
config['app_path'] = str(target)
config['dockerfile_path'] = config.get('dockerfile_path') or 'Dockerfile'
method = config.get('build_method', 'auto')
if method == 'auto':
method = BuildService.detect_build_method(str(target))['build_method']
if method not in ('dockerfile', 'nixpacks'):
raise PreviewError('Previews require a Dockerfile or container buildpack; host-command builds are disabled.')
config['build_method'] = method
relative_file(target, config.get('dockerfile_path') or 'Dockerfile')
relative_file(target, 'Dockerfile.serverkit')
# Detect the PR's source, not the parent branch's persisted plan. Parent
# build secrets are not implicitly handed to PR code.
config.pop('buildpack_plan', None)
config['build_args'] = {}
config['env_vars'] = {}
result = BuildService.build_from_config(
f'preview-{preview.id}', config, image_tag=image, log_callback=log_callback,
)
if not result.get('success'):
raise PreviewError('Preview image build failed. See the preview job logs.')