Esempio n. 1
0
def sign_tarball(tarball_path):
    """ Prompt the user to GPG-sign the tarball using their Apache GPG key. """
    if not confirm_prompt("Would you like to GPG-sign the tarball now?"):
        return

    email = get_my_email()
    if not email.endswith("@apache.org"):
        print(
            Colors.YELLOW,
            "Your email address for the repository is not an @apache.org address."
        )
        print(
            "Release signatures should typically be signed by committers with @apache.org GPG keys."
        )
        print(end=Colors.RESET)
        if not confirm_prompt("Continue?"):
            return

    try:
        subprocess.check_call(
            ["gpg", "--detach-sign", "--armor", "-u", email, tarball_path])
    except subprocess.CalledProcessError:
        print(Colors.RED + "GPG signing failed. Artifact will not be signed." +
              Colors.RESET)
        return
    print(Colors.GREEN + "Generated signature:\t" + Colors.RESET,
          tarball_path + ".asc")
Esempio n. 2
0
def check_repo_not_dirty():
    """Check that the git repository isn't dirty."""
    dirty_repo = subprocess.call("git diff --quiet && git diff --cached --quiet", shell=True) != 0
    if not dirty_repo:
        return
    print "The repository does not appear to be clean."
    print Colors.RED + "The source release will not include your local changes." + Colors.RESET
    if not confirm_prompt("Continue?"):
        sys.exit(1)
Esempio n. 3
0
def sign_tarball(tarball_path):
  """ Prompt the user to GPG-sign the tarball using their Apache GPG key. """
  if not confirm_prompt("Would you like to GPG-sign the tarball now?"):
    return

  email = get_my_email()
  if not email.endswith("@apache.org"):
    print(Colors.YELLOW, "Your email address for the repository is not an @apache.org address.")
    print("Release signatures should typically be signed by committers with @apache.org GPG keys.")
    print(end=Colors.RESET)
    if not confirm_prompt("Continue?"):
      return

  try:
    subprocess.check_call(["gpg", "--detach-sign", "--armor", "-u", email, tarball_path])
  except subprocess.CalledProcessError:
    print(Colors.RED + "GPG signing failed. Artifact will not be signed." + Colors.RESET)
    return
  print(Colors.GREEN + "Generated signature:\t" + Colors.RESET, tarball_path + ".asc")
Esempio n. 4
0
def check_repo_not_dirty():
  """Check that the git repository isn't dirty."""
  dirty_repo = subprocess.call("git diff --quiet && git diff --cached --quiet",
                               shell=True) != 0
  if not dirty_repo:
    return
  print("The repository does not appear to be clean.")
  print(Colors.RED + "The source release will not include your local changes." + Colors.RESET)
  if not confirm_prompt("Continue?"):
    sys.exit(1)
Esempio n. 5
0
def do_update(branch, gerrit_sha, apache_sha):
    """
  Displays and performs a proposed update of the Apache repository
  for branch 'branch' from 'apache_sha' to 'gerrit_sha'.
  """
    # First, verify that the update is fast-forward. If it's not, then something
    # must have gotten committed to Apache outside of gerrit, and we'd need some
    # manual intervention.
    if not is_fast_forward(apache_sha, gerrit_sha):
        print >> sys.stderr, "Cannot update branch '%s' from gerrit:" % branch
        print >> sys.stderr, "Apache revision %s is not an ancestor of gerrit revision %s" % (
            apache_sha[:8], gerrit_sha[:8])
        print >> sys.stderr, "Something must have been committed to Apache and bypassed gerrit."
        print >> sys.stderr, "Manual intervention is required."
        sys.exit(1)

    # List the commits that are going to be pushed to the ASF, so that the committer
    # can verify and "sign off".
    commits = rev_list("%s..%s" % (apache_sha, gerrit_sha))
    commits.reverse()  # Display from oldest to newest.
    print "-" * 60
    print Colors.GREEN + ("%d commit(s) need to be pushed from Gerrit to ASF:"
                          % len(commits)) + Colors.RESET
    push_sha = None
    for sha in commits:
        oneline = describe_commit(sha)
        print "  ", oneline
        committer = get_committer_email(sha)
        if committer != get_my_email():
            print Colors.RED + "   !!! Committed by someone else (%s) !!!" % committer, Colors.RESET
            if not confirm_prompt(
                    Colors.RED +
                    "   !!! Are you sure you want to push on behalf of another committer?"
                    + Colors.RESET):
                # Even if they don't want to push this commit, we could still push any
                # earlier commits that the user _did_ author.
                if push_sha is not None:
                    print "... will still update to prior commit %s..." % push_sha
                break
        push_sha = sha
    if push_sha is None:
        print "Nothing to push"
        return

    # Everything has been confirmed. Do the actual push
    cmd = ['git', 'push', 'apache']
    if OPTIONS.dry_run:
        cmd.append('--dry-run')
    cmd.append('%s:refs/heads/%s' % (push_sha, branch))
    print Colors.GREEN + "Running: " + Colors.RESET + " ".join(cmd)
    subprocess.check_call(cmd)
    print Colors.GREEN + "Successfully updated %s to %s" % (
        branch, gerrit_sha) + Colors.RESET
    print
Esempio n. 6
0
def do_update(branch, gerrit_sha, apache_sha):
  """
  Displays and performs a proposed update of the Apache repository
  for branch 'branch' from 'apache_sha' to 'gerrit_sha'.
  """
  # First, verify that the update is fast-forward. If it's not, then something
  # must have gotten committed to Apache outside of gerrit, and we'd need some
  # manual intervention.
  if not is_fast_forward(apache_sha, gerrit_sha):
    print >>sys.stderr, "Cannot update branch '%s' from gerrit:" % branch
    print >>sys.stderr, "Apache revision %s is not an ancestor of gerrit revision %s" % (
      apache_sha[:8], gerrit_sha[:8])
    print >>sys.stderr, "Something must have been committed to Apache and bypassed gerrit."
    print >>sys.stderr, "Manual intervention is required."
    sys.exit(1)

  # List the commits that are going to be pushed to the ASF, so that the committer
  # can verify and "sign off".
  commits = rev_list("%s..%s" % (apache_sha, gerrit_sha))
  commits.reverse()  # Display from oldest to newest.
  print "-" * 60
  print Colors.GREEN + ("%d commit(s) need to be pushed from Gerrit to ASF:" % len(commits)) + Colors.RESET
  push_sha = None
  for sha in commits:
    oneline = describe_commit(sha)
    print "  ", oneline
    committer = get_committer_email(sha)
    if committer != get_my_email():
      print Colors.RED + "   !!! Committed by someone else (%s) !!!" % committer, Colors.RESET
      if not confirm_prompt(
          Colors.RED + "   !!! Are you sure you want to push on behalf of another committer?" + Colors.RESET):
        # Even if they don't want to push this commit, we could still push any
        # earlier commits that the user _did_ author.
        if push_sha is not None:
          print "... will still update to prior commit %s..." % push_sha
        break
    push_sha = sha
  if push_sha is None:
    print "Nothing to push"
    return

  # Everything has been confirmed. Do the actual push
  cmd = ['git', 'push', 'apache']
  if OPTIONS.dry_run:
    cmd.append('--dry-run')
  cmd.append('%s:refs/heads/%s' % (push_sha, branch))
  print Colors.GREEN + "Running: " + Colors.RESET + " ".join(cmd)
  subprocess.check_call(cmd)
  print Colors.GREEN + "Successfully updated %s to %s" % (branch, gerrit_sha) + Colors.RESET
  print
Esempio n. 7
0
def check_no_local_commits():
  """
  Check that there are no local commits which haven't been pushed to the upstream
  repo via Jenkins.
  """
  upstream_commit = get_upstream_commit()
  cur_commit = check_output(["git", "rev-parse", "HEAD"]).strip().decode('utf-8')

  if upstream_commit == cur_commit:
    return
  print("The repository appears to have local commits:")
  subprocess.check_call(["git", "log", "--oneline", "%s..HEAD" % upstream_commit])

  print(Colors.RED + "This should not be an official release!" + Colors.RESET)
  if not confirm_prompt("Continue?"):
    sys.exit(1)
Esempio n. 8
0
def run_rat(tarball_path):
    """
  Run Apache RAT on the source tarball.

  Raises an exception on failure.
  """
    if not confirm_prompt(
            "Would you like to run Apache RAT (Release Audit Tool) now?"):
        return

    # TODO: Cache and call the jar from the maven repo?
    rat_url = "https://search.maven.org/remotecontent?filepath=org/apache/rat/apache-rat/0.13/apache-rat-0.13.jar"

    tmpdir_path = tempfile.mkdtemp()
    rat_report_result = ''
    try:
        rat_jar_dest = "%s/%s" % (tmpdir_path, os.path.basename(rat_url))

        print("> Downloading RAT jar from " + rat_url)
        urllib.urlretrieve(rat_url, rat_jar_dest)

        print("> Running RAT...")
        xml = subprocess.check_output(
            ["java", "-jar", rat_jar_dest, "-x", tarball_path])
        rat_report_dest = "%s/%s" % (tmpdir_path, "rat_report.xml")
        with open(rat_report_dest, "wb") as f:
            f.write(xml)

        print("> Parsing RAT report...")
        rat_report_result = subprocess.check_output(
            [
                "./build-support/release/check-rat-report.py",
                "./build-support/release/rat_exclude_files.txt",
                rat_report_dest
            ],
            stderr=subprocess.STDOUT).decode('utf-8')
        print(Colors.GREEN + "RAT: LICENSES APPROVED" + Colors.RESET)
    except subprocess.CalledProcessError as e:
        print(Colors.RED + "RAT: LICENSES NOT APPROVED" + Colors.RESET)
        print(e.output.decode('utf-8'))
        raise e
    finally:
        shutil.rmtree(tmpdir_path)
Esempio n. 9
0
def run_rat(tarball_path):
    """
  Run Apache RAT on the source tarball.

  Raises an exception on failure.
  """
    if not confirm_prompt("Would you like to run Apache RAT (Release Audit Tool) now?"):
        return

    # TODO: Cache and call the jar from the maven repo?
    rat_url = "http://central.maven.org/maven2/org/apache/rat/apache-rat/0.11/apache-rat-0.11.jar"

    tmpdir_path = tempfile.mkdtemp()
    rat_report_result = ""
    try:
        rat_jar_dest = "%s/%s" % (tmpdir_path, os.path.basename(rat_url))

        print "> Downloading RAT jar from " + rat_url
        urllib.urlretrieve(rat_url, rat_jar_dest)

        print "> Running RAT..."
        xml = subprocess.check_output(["java", "-jar", rat_jar_dest, "-x", tarball_path])
        rat_report_dest = "%s/%s" % (tmpdir_path, "rat_report.xml")
        with open(rat_report_dest, "w") as f:
            f.write(xml)

        print "> Parsing RAT report..."
        rat_report_result = subprocess.check_output(
            [
                "./build-support/release/check-rat-report.py",
                "./build-support/release/rat_exclude_files.txt",
                rat_report_dest,
            ],
            stderr=subprocess.STDOUT,
        )
        print Colors.GREEN + "RAT: LICENSES APPROVED" + Colors.RESET
    except subprocess.CalledProcessError as e:
        print Colors.RED + "RAT: LICENSES NOT APPROVED" + Colors.RESET
        print e.output
        raise e
    finally:
        shutil.rmtree(tmpdir_path)