Beispiel #1
0
def view_build(path):
    build = get_target_for(path)
    if not isinstance(build, Build):
        return abort(404)

    restart = request.args.get('restart', '').strip().lower() == 'true'
    if restart:
        if build.status != Build.Status_Building:
            build.delete_build()
            build.status = Build.Status_Queued
            build.date_started = None
            build.date_finished = None
            models.commit()
            enqueue(build)
        return redirect(build.url())

    stop = request.args.get('stop', '').strip().lower() == 'true'
    if stop:
        if build.status == Build.Status_Queued:
            build.status = Build.Status_Stopped
        elif build.status == Build.Status_Building:
            terminate_build(build)
        return redirect(build.url())

    return render_template('view_build.html', user=request.user, build=build)
Beispiel #2
0
def build():
    repo_id = request.args.get('repo_id', '')
    ref_name = request.args.get('ref', '')
    if not repo_id or not ref_name:
        return abort(400)
    if not request.user.can_manage:
        return abort(403)

    commit = '0' * 32
    repo = Repository.get(id=repo_id)
    build = Build(repo=repo,
                  commit_sha=commit,
                  num=repo.build_count,
                  ref=ref_name,
                  status=Build.Status_Queued,
                  date_queued=datetime.now(),
                  date_started=None,
                  date_finished=None)
    repo.build_count += 1

    models.commit()
    enqueue(build)
    return redirect(repo.url())
Beispiel #3
0
def hook_push(logger):
    ''' PUSH event webhook. The URL parameter ``api`` must be specified
  for Flux to expect the correct JSON payload format. Supported values
  for ``api`` are

  * ``gogs``
  * ``github``
  * ``gitea``
  * ``gitbucket``
  * ``bitbucket``
  * ``bitbucket-cloud``
  * ``gitlab``
  * ``bare``

  If no or an invalid value is specified for this parameter, a 400
  Invalid Request response is generator. '''

    api = request.args.get('api')
    if api not in (API_GOGS, API_GITHUB, API_GITEA, API_GITBUCKET,
                   API_BITBUCKET, API_BITBUCKET_CLOUD, API_GITLAB, API_BARE):
        logger.error('invalid `api` URL parameter: {!r}'.format(api))
        return 400

    logger.info('PUSH event received. Processing JSON payload.')
    try:
        # XXX Determine encoding from Request Headers, if possible.
        data = json.loads(request.data.decode('utf8'))
    except (UnicodeDecodeError, ValueError) as exc:
        logger.error('Invalid JSON data received: {}'.format(exc))
        return 400

    if api == API_GOGS:
        owner = utils.get(data, 'repository.owner.username', str)
        name = utils.get(data, 'repository.name', str)
        ref = utils.get(data, 'ref', str)
        commit = utils.get(data, 'after', str)
        secret = utils.get(data, 'secret', str)
        get_repo_secret = lambda r: r.secret
    elif api == API_GITHUB:
        event = request.headers.get('X-Github-Event')
        if event != 'push':
            logger.error(
                "Payload rejected (expected 'push' event, got {!r})".format(
                    event))
            return 400
        owner = utils.get(data, 'repository.owner.name', str)
        name = utils.get(data, 'repository.name', str)
        ref = utils.get(data, 'ref', str)
        commit = utils.get(data, 'after', str)
        secret = request.headers.get('X-Hub-Signature',
                                     '').replace('sha1=', '')
        get_repo_secret = lambda r: utils.get_github_signature(
            r.secret, request.data)
    elif api == API_GITEA:
        event = request.headers.get('X-Gitea-Event')
        if event != 'push':
            logger.error(
                "Payload rejected (expected 'push' event, got {!r})".format(
                    event))
            return 400
        owner = utils.get(data, 'repository.owner.username', str)
        name = utils.get(data, 'repository.name', str)
        ref = utils.get(data, 'ref', str)
        commit = utils.get(data, 'after', str)
        secret = utils.get(data, 'secret', str)
        get_repo_secret = lambda r: r.secret
    elif api == API_GITBUCKET:
        event = request.headers.get('X-Github-Event')
        if event != 'push':
            logger.error(
                "Payload rejected (expected 'push' event, got {!r})".format(
                    event))
            return 400
        owner = utils.get(data, 'repository.owner.login', str)
        name = utils.get(data, 'repository.name', str)
        ref = utils.get(data, 'ref', str)
        commit = utils.get(data, 'after', str)
        secret = request.headers.get('X-Hub-Signature',
                                     '').replace('sha1=', '')
        if secret:
            get_repo_secret = lambda r: utils.get_github_signature(
                r.secret, request.data)
        else:
            get_repo_secret = lambda r: r.secret
    elif api == API_BITBUCKET:
        event = request.headers.get('X-Event-Key')
        if event != 'repo:refs_changed':
            logger.error(
                "Payload rejected (expected 'repo:refs_changed' event, got {!r})"
                .format(event))
            return 400
        owner = utils.get(data, 'repository.project.name', str)
        name = utils.get(data, 'repository.name', str)
        ref = utils.get(data, 'changes.0.refId', str)
        commit = utils.get(data, 'changes.0.toHash', str)
        secret = request.headers.get('X-Hub-Signature',
                                     '').replace('sha256=', '')
        if secret:
            get_repo_secret = lambda r: utils.get_bitbucket_signature(
                r.secret, request.data)
        else:
            get_repo_secret = lambda r: r.secret
    elif api == API_BITBUCKET_CLOUD:
        event = request.headers.get('X-Event-Key')
        if event != 'repo:push':
            logger.error(
                "Payload rejected (expected 'repo:push' event, got {!r})".
                format(event))
            return 400
        owner = utils.get(data, 'repository.project.project', str)
        name = utils.get(data, 'repository.name', str)

        ref_type = utils.get(data, 'push.changes.0.new.type', str)
        ref_name = utils.get(data, 'push.changes.0.new.name', str)
        ref = "refs/" + ("heads/"
                         if ref_type == "branch" else "tags/") + ref_name

        commit = utils.get(data, 'push.changes.0.new.target.hash', str)
        secret = None
        get_repo_secret = lambda r: r.secret
    elif api == API_GITLAB:
        event = utils.get(data, 'object_kind', str)
        if event != 'push' and event != 'tag_push':
            logger.error(
                "Payload rejected (expected 'push' or 'tag_push' event, got {!r})"
                .format(event))
            return 400
        owner = utils.get(data, 'project.namespace', str)
        name = utils.get(data, 'project.name', str)
        ref = utils.get(data, 'ref', str)
        commit = utils.get(data, 'checkout_sha', str)
        secret = request.headers.get('X-Gitlab-Token')
        get_repo_secret = lambda r: r.secret
    elif api == API_BARE:
        owner = utils.get(data, 'owner', str)
        name = utils.get(data, 'name', str)
        ref = utils.get(data, 'ref', str)
        commit = utils.get(data, 'commit', str)
        secret = utils.get(data, 'secret', str)
        get_repo_secret = lambda r: r.secret
    else:
        assert False, "unreachable"

    if not name:
        logger.error('invalid JSON: no repository name received')
        return 400
    if not owner:
        logger.error('invalid JSON: no repository owner received')
        return 400
    if not ref:
        logger.error('invalid JSON: no Git ref received')
        return 400
    if not commit:
        logger.error('invalid JSON: no commit SHA received')
        return 400
    if len(commit) != 40:
        logger.error('invalid JSON: commit SHA has invalid length')
        return 400
    if secret == None:
        secret = ''

    name = owner + '/' + name

    repo = Repository.get(name=name)
    if not repo:
        logger.error('PUSH event rejected (unknown repository)')
        return 400
    if get_repo_secret(repo) != secret:
        logger.error('PUSH event rejected (invalid secret)')
        return 400
    if not repo.check_accept_ref(ref):
        logger.info(
            'Git ref {!r} not whitelisted. No build dispatched'.format(ref))
        return 200

    build = Build(repo=repo,
                  commit_sha=commit,
                  num=repo.build_count,
                  ref=ref,
                  status=Build.Status_Queued,
                  date_queued=datetime.now(),
                  date_started=None,
                  date_finished=None)
    repo.build_count += 1

    models.commit()
    enqueue(build)
    logger.info('Build #{} for repository {} queued'.format(
        build.num, repo.name))
    logger.info(utils.strip_url_path(config.app_url) + build.url())
    return 200