prepare_release_create_release_version.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. # Licensed to Elasticsearch under one or more contributor
  2. # license agreements. See the NOTICE file distributed with
  3. # this work for additional information regarding copyright
  4. # ownership. Elasticsearch licenses this file to you under
  5. # the Apache License, Version 2.0 (the "License"); you may
  6. # not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing,
  12. # software distributed under the License is distributed on
  13. # an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  14. # either express or implied. See the License for the specific
  15. # language governing permissions and limitations under the License.
  16. # Prepare a release
  17. #
  18. # 1. Update the Version.java to remove the snapshot bit
  19. # 2. Remove the -SNAPSHOT suffix in all pom.xml files
  20. #
  21. # USAGE:
  22. #
  23. # python3 ./dev-tools/prepare-release.py
  24. #
  25. # Note: Ensure the script is run from the root directory
  26. #
  27. import fnmatch
  28. import subprocess
  29. import tempfile
  30. import re
  31. import os
  32. import shutil
  33. VERSION_FILE = 'core/src/main/java/org/elasticsearch/Version.java'
  34. POM_FILE = 'pom.xml'
  35. def run(command):
  36. if os.system('%s' % (command)):
  37. raise RuntimeError(' FAILED: %s' % (command))
  38. def ensure_checkout_is_clean():
  39. # Make sure no local mods:
  40. s = subprocess.check_output('git diff --shortstat', shell=True)
  41. if len(s) > 0:
  42. raise RuntimeError('git diff --shortstat is non-empty: got:\n%s' % s)
  43. # Make sure no untracked files:
  44. s = subprocess.check_output('git status', shell=True).decode('utf-8', errors='replace')
  45. if 'Untracked files:' in s:
  46. raise RuntimeError('git status shows untracked files: got:\n%s' % s)
  47. # Make sure we have all changes from origin:
  48. if 'is behind' in s:
  49. raise RuntimeError('git status shows not all changes pulled from origin; try running "git pull origin" in this branch: got:\n%s' % (s))
  50. # Make sure we no local unpushed changes (this is supposed to be a clean area):
  51. if 'is ahead' in s:
  52. raise RuntimeError('git status shows local commits; try running "git fetch origin", "git checkout ", "git reset --hard origin/" in this branch: got:\n%s' % (s))
  53. # Reads the given file and applies the
  54. # callback to it. If the callback changed
  55. # a line the given file is replaced with
  56. # the modified input.
  57. def process_file(file_path, line_callback):
  58. fh, abs_path = tempfile.mkstemp()
  59. modified = False
  60. with open(abs_path,'w', encoding='utf-8') as new_file:
  61. with open(file_path, encoding='utf-8') as old_file:
  62. for line in old_file:
  63. new_line = line_callback(line)
  64. modified = modified or (new_line != line)
  65. new_file.write(new_line)
  66. os.close(fh)
  67. if modified:
  68. #Remove original file
  69. os.remove(file_path)
  70. #Move new file
  71. shutil.move(abs_path, file_path)
  72. return True
  73. else:
  74. # nothing to do - just remove the tmp file
  75. os.remove(abs_path)
  76. return False
  77. # Moves the Version.java file from a snapshot to a release
  78. def remove_version_snapshot(version_file, release):
  79. # 1.0.0.Beta1 -> 1_0_0_Beta1
  80. release = release.replace('.', '_')
  81. release = release.replace('-', '_')
  82. pattern = 'new Version(V_%s_ID, true' % (release)
  83. replacement = 'new Version(V_%s_ID, false' % (release)
  84. def callback(line):
  85. return line.replace(pattern, replacement)
  86. processed = process_file(version_file, callback)
  87. if not processed:
  88. raise RuntimeError('failed to remove snapshot version for %s' % (release))
  89. # Checks the pom.xml for the release version.
  90. # This method fails if the pom file has no SNAPSHOT version set ie.
  91. # if the version is already on a release version we fail.
  92. # Returns the next version string ie. 0.90.7
  93. def find_release_version():
  94. with open('pom.xml', encoding='utf-8') as file:
  95. for line in file:
  96. match = re.search(r'<version>(.+)-SNAPSHOT</version>', line)
  97. if match:
  98. return match.group(1)
  99. raise RuntimeError('Could not find release version in branch')
  100. if __name__ == "__main__":
  101. release_version = find_release_version()
  102. print('*** Preparing release version: [%s]' % release_version)
  103. ensure_checkout_is_clean()
  104. run('cd dev-tools && mvn versions:set -DnewVersion=%s -DgenerateBackupPoms=false' % (release_version))
  105. run('cd rest-api-spec && mvn versions:set -DnewVersion=%s -DgenerateBackupPoms=false' % (release_version))
  106. run('mvn versions:set -DnewVersion=%s -DgenerateBackupPoms=false' % (release_version))
  107. remove_version_snapshot(VERSION_FILE, release_version)
  108. print('*** Done removing snapshot version. DO NOT COMMIT THIS, WHEN CREATING A RELEASE CANDIDATE.')
  109. shortHash = subprocess.check_output('git log --pretty=format:"%h" -n 1', shell=True).decode('utf-8')
  110. localRepo = '/tmp/elasticsearch-%s-%s' % (release_version, shortHash)
  111. localRepoElasticsearch = localRepo + '/org/elasticsearch'
  112. print('')
  113. print('*** To create a release candidate run: ')
  114. print(' mvn clean install deploy -Prelease -DskipTests -Dgpg.keyname="D88E42B4" -Dpackaging.rpm.rpmbuild=/usr/bin/rpmbuild -Drpm.sign=true -Dmaven.repo.local=%s -Dno.commit.pattern="\\bno(n|)commit\\b" -Dforbidden.test.signatures=""' % (localRepo))
  115. print(' 1. Remove all _remote.repositories: find %s -name _remote.repositories -exec rm {} \;' % (localRepoElasticsearch))
  116. print(' 2. Rename all maven metadata files: for i in $(find %s -name "maven-metadata-local.xml*") ; do mv "$i" "${i/-local/}" ; done' % (localRepoElasticsearch))
  117. print(' 3. Sync %s into S3 bucket' % (localRepoElasticsearch))
  118. print (' s3cmd sync %s s3://download.elasticsearch.org/elasticsearch/staging/elasticsearch-%s-%s/maven/org/' % (localRepoElasticsearch, release_version, shortHash))
  119. print(' 4. Create repositories: ')
  120. print (' export S3_BUCKET_SYNC_TO="download.elasticsearch.org/elasticsearch/staging/elasticsearch-%s-%s/repos"' % (release_version, shortHash))
  121. print (' export S3_BUCKET_SYNC_FROM="$S3_BUCKET_SYNC_TO"')
  122. print(' dev-tools/build_repositories.sh %s' % (release_version))
  123. print('')
  124. print('NOTE: the above mvn command will promt you several times for the GPG passphrase of the key you specified you can alternatively pass it via -Dgpg.passphrase=yourPassPhrase')
  125. print('NOTE: Running s3cmd might require you to create a config file with your credentials, if the s3cmd does not support suppliying them via the command line!')