#!/usr/bin/env python
import re
import requests
import subprocess
import os
release_template = """
_rqlite_ is a lightweight , distributed relational database , which uses [ SQLite ] ( https : / / www . sqlite . org / ) as its storage engine . rqlite provides an easy - to - use , fault - tolerant store for your most important relational data . You can learn a lot more about rqlite at [ rqlite . io ] ( https : / / www . rqlite . io ) .
Release { release } { release_specific_notes } . See the [ CHANGELOG ] ( https : / / github . com / rqlite / rqlite / blob / master / CHANGELOG . md ) for full details on this release , and check out the _Assets_ section below for prebuilt binaries .
## Getting started
To download and run a single rqlite node follow the directions below . It ' s also very easy to run a rqlite cluster -- you can learn more by checking out the [documentation](https://rqlite.io/docs/clustering/).
If you wish to build rqlite from source , check out [ this documentation ] ( https : / / github . com / rqlite / rqlite / blob / master / CONTRIBUTING . md ) .
### Docker
Run a single node as follows :
` ` `
docker pull rqlite / rqlite
docker run - p4001 : 4001 rqlite / rqlite
` ` `
Check out the [ rqlite Docker page ] ( https : / / hub . docker . com / r / rqlite / rqlite / ) for more details on running nodes via Docker .
### Linux
_Builds for a variety of CPU architectures are available . See the Assets section below . _
To download and start rqlite , execute the following in a shell .
` ` `
curl - L https : / / github . com / rqlite / rqlite / releases / download / { release } / rqlite - { release } - linux - amd64 . tar . gz - o rqlite - { release } - linux - amd64 . tar . gz
tar xvfz rqlite - { release } - linux - amd64 . tar . gz
cd rqlite - { release } - linux - amd64
. / rqlited ~ / node .1
` ` `
### macOS
` ` `
homebrew rqlite
` ` `
#### Homebrew
` ` ` brew install rqlite ` ` `
### Windows
rqlite can be built for Windows , and Windows compatibility is ensured via [ AppVeyor ] ( https : / / www . appveyor . com / ) . However you may need to build a specific release yourself , though the top - of - tree build [ is available for download ] ( https : / / ci . appveyor . com / api / projects / otoolep / rqlite / artifacts / rqlite - latest - win64 . zip ? branch = master ) from AppVeyor . Check out the [ CI build for Windows ] ( https : / / ci . appveyor . com / project / otoolep / rqlite ) for more details . Please note that I do not control the build process in AppVeyor and you download and use those binaries at your own risk .
"""
def generate_release_notes ( release , features ) :
return release_template . format ( release = release , release_specific_notes = features )
def validate_release_string ( release_str ) :
pattern = re . compile ( r ' ^v \ d+ \ . \ d+ \ . \ d+$ ' )
return pattern . match ( release_str )
def get_release_string ( ) :
while True :
release_str = input ( " Enter a release string in the format vX.Y.Z: " )
if validate_release_string ( release_str ) :
return release_str
else :
print ( " Invalid release string. Please try again. " )
def get_github_token ( ) :
token = input ( " Enter your GitHub Personal Access Token: " )
return token
def get_release_features ( ) :
notes = input ( " Enter release features: " )
return notes
def create_github_release ( release_str , token , notes ) :
headers = {
' Authorization ' : f ' token { token } ' ,
' Accept ' : ' application/vnd.github+json '
}
data = {
' tag_name ' : release_str ,
' name ' : release_str ,
' body ' : notes
}
url = ' https://api.github.com/repos/rqlite/rqlite/releases '
response = requests . post ( url , headers = headers , json = data )
if response . status_code != 201 :
response . raise_for_status ( )
return response . json ( ) [ ' id ' ]
def confirm_bash_command ( command ) :
print ( " \n About to run the following bash command: " )
print ( " " . join ( command ) )
confirmation = input ( " \n Do you want to proceed? (yes/no): " )
return confirmation . lower ( ) == " yes "
def invoke_package_script ( release_str , release_id , token ) :
if os . path . exists ( ' package.sh ' ) :
command = [ ' ./package.sh ' , release_str , str ( release_id ) , token ]
if confirm_bash_command ( command ) :
subprocess . run ( command , check = True )
else :
print ( " Aborting program. " )
exit ( 1 )
else :
print ( " package.sh not found. Please ensure it ' s in the current working directory. " )
def confirm_CHANGELOG ( ) :
confirmation = input ( " Have you dated the CHANGELOG?: " )
return confirmation . lower ( ) == " yes "
def confirm_release_notes ( release_notes ) :
print ( " \n Release Notes: " )
print ( release_notes )
confirmation = input ( " \n Do the release notes look good? (yes/no): " )
return confirmation . lower ( ) == " yes "
def main ( ) :
while True :
if not confirm_CHANGELOG ( ) :
continue
release_str = get_release_string ( )
features = get_release_features ( )
release_notes = generate_release_notes ( release_str , features )
if confirm_release_notes ( release_notes ) :
break
else :
print ( " Please enter the release string and release-specific notes again. \n " )
token = get_github_token ( )
try :
release_id = create_github_release ( release_str , token , release_notes )
print ( f " Release created with ID: { release_id } " )
invoke_package_script ( release_str , release_id , token )
except requests . HTTPError as e :
print ( f " An error occurred while creating the release: { e } " )
except subprocess . CalledProcessError as e :
print ( f " An error occurred while running package.sh: { e } " )
except Exception as e :
print ( f " An unexpected error occurred: { e } " )
if __name__ == " __main__ " :
main ( )