Skip to content

Commit

Permalink
allow passing of version, commit and dates to release creation
Browse files Browse the repository at this point in the history
  • Loading branch information
yeoldegrove committed Oct 15, 2024
1 parent 6d50655 commit b9d6152
Showing 1 changed file with 112 additions and 80 deletions.
192 changes: 112 additions & 80 deletions glrd-create
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@ def create_releases(releases):

# Determine release type: "patch" if minor exists, otherwise "stable"
release_type = "patch" if minor is not None else "stable"
# DEBUG
# print(f"Processing {release_type} release: {tag_name}")

release_info = {
"name": f"release-{tag_name}",
Expand Down Expand Up @@ -369,14 +371,20 @@ def create_releases(releases):
'minor': minor
}

# release_data.append(release_info)

# return release_data, release_data_stable, release_data_patch, latest_minor_versions
return release_data_stable, release_data_patch, latest_minor_versions

def create_nightly_releases(releases, start_date):
def create_nightly_releases(stable_releases):
"""Generate nightly releases from the earliest stable release."""
release_data = []

start_date_default = datetime(2020, 6, 9)
if len(stable_releases) > 0: # If stable/patch releases were generated
first_stable_release = min(stable_releases, key=lambda r: r['lifecycle']['released']['timestamp'])
start_date = datetime.utcfromtimestamp(first_stable_release['lifecycle']['released']['timestamp'])
else:
print("No stable releases found in the generated data. Using default start date.")
start_date = start_date_default

tz = pytz.timezone('UTC')
start_date = tz.localize(start_date)
current_date = datetime.now(tz)
Expand All @@ -401,20 +409,61 @@ def create_nightly_releases(releases, start_date):

return release_data

def create_single_release(release_type):
"""Generate a release using the release_type, current timestamp and git info."""
# Get the current date and timestamp
tz = pytz.timezone('UTC')
current_date = tz.localize(datetime.now())
isodate = current_date.strftime('%Y-%m-%d')
timestamp = int(current_date.timestamp())
def create_single_release(release_type, args):
"""Generate a release using the release_type, current timestamp and git info, or using provided arguments."""
# Check if a manual date-time-released is provided, otherwise use the current date
if args.date_time_released:
try:
release_date = datetime.strptime(args.date_time_released, "%Y-%m-%dT%H:%M:%S").replace(tzinfo=pytz.UTC)
except ValueError:
sys.exit("Error: Invalid --date-time-release format. Use ISO format: YYYY-MM-DDTHH:MM:SS")
else:
tz = pytz.timezone('UTC')
release_date = tz.localize(datetime.now())

lifecycle_released_isodate = release_date.strftime('%Y-%m-%d')
lifecycle_released_timestamp = int(release_date.timestamp())

# Get the git commit and short commit
commit, commit_short = get_git_commit_at_time(isodate)
if args.date_time_extended:
try:
extended_date = datetime.strptime(args.date_time_released, "%Y-%m-%dT%H:%M:%S").replace(tzinfo=pytz.UTC)
lifecycle_extended_isodate = extended_date.strftime('%Y-%m-%d')
lifecycle_extended_timestamp = int(extended_date.timestamp())
except ValueError:
sys.exit("Error: Invalid --date-time-extended format. Use ISO format: YYYY-MM-DDTHH:MM:SS")
else:
lifecycle_extended_isodate = None
lifecycle_extended_timestamp = None

# Get the garden version for the current date
version = get_garden_version_for_date(current_date, nightly=False)
major, minor = map(int, version.split('.'))
if args.date_time_eol:
try:
eol_date = datetime.strptime(args.date_time_released, "%Y-%m-%dT%H:%M:%S").replace(tzinfo=pytz.UTC)
lifecycle_eol_isodate = eol_date.strftime('%Y-%m-%d')
lifecycle_eol_timestamp = int(eol_date.timestamp())
except ValueError:
sys.exit("Error: Invalid --date-time-eol format. Use ISO format: YYYY-MM-DDTHH:MM:SS")
else:
lifecycle_eol_isodate = None
lifecycle_eol_timestamp = None

# Check if a manual commit is provided, otherwise use git commit at the given time
if args.commit:
commit = args.commit
if len(commit) != 40:
sys.exit("Error: Invalid commit hash. Must be 40 characters.")
commit_short = commit[:7]
else:
commit, commit_short = get_git_commit_at_time(isodate)

# Check if a manual version is provided, otherwise use garden version for the date
if args.version:
try:
major, minor = map(int, args.version.split('.'))
except ValueError:
sys.exit("Error: Invalid --version format. Use format: major.minor")
else:
version = get_garden_version_for_date(current_date, nightly=False)
major, minor = map(int, version.split('.'))

# Create release data
release = {}
Expand All @@ -423,8 +472,8 @@ def create_single_release(release_type):
release['version']['major'] = major
release['lifecycle'] = {}
release['lifecycle']['released'] = {}
release['lifecycle']['released']['isodate'] = isodate
release['lifecycle']['released']['timestamp'] = timestamp
release['lifecycle']['released']['isodate'] = lifecycle_released_isodate
release['lifecycle']['released']['timestamp'] = lifecycle_released_timestamp

if release_type in ['dev', 'nightly']:
release['name'] = f"{release_type}-{major}.{minor}"
Expand All @@ -435,17 +484,17 @@ def create_single_release(release_type):
elif release_type == "stable":
release['name'] = f"{release_type}-{major}"
release['lifecycle']['extended'] = {}
release['lifecycle']['extended']['isodate'] = None
release['lifecycle']['extended']['timestamp'] = None
release['lifecycle']['extended']['isodate'] = lifecycle_extended_isodate
release['lifecycle']['extended']['timestamp'] = lifecycle_extended_timestamp
release['lifecycle']['eol'] = {}
release['lifecycle']['eol']['isodate'] = None
release['lifecycle']['eol']['timestamp'] = None
release['lifecycle']['eol']['isodate'] = lifecycle_eol_isodate
release['lifecycle']['eol']['timestamp'] = lifecycle_eol_timestamp
elif release_type == "patch":
release['name'] = f"{release_type}-{major}.{minor}"
release['version']['minor'] = minor
release['lifecycle']['eol'] = {}
release['lifecycle']['eol']['isodate'] = None
release['lifecycle']['eol']['timestamp'] = None
release['lifecycle']['eol']['isodate'] = lifecycle_eol_isodate
release['lifecycle']['eol']['timestamp'] = lifecycle_eol_timestamp
release['git'] = {}
release['git']['commit'] = commit
release['git']['commit_short'] = commit_short
Expand All @@ -454,7 +503,6 @@ def create_single_release(release_type):

return release


def merge_input_data(auto_data, manual_data):
"""Merge two lists of release data, avoiding duplicates."""
# Assuming auto_data and manual_data are both lists
Expand All @@ -470,16 +518,13 @@ def merge_input_data(auto_data, manual_data):



def set_latest_minor_eol_to_major(releases):
def set_latest_minor_eol_to_major(stable_releases, patch_releases):
"""Set the EOL of each minor version to the next higher minor version,
and the EOL of the latest minor version to match the stable release."""
releases_by_major = {}

# Group releases by major version
for release in releases:
if release.get('type') == 'stable':
continue # Skip stable releases in the initial grouping

for release in patch_releases:
major = release['version']['major']
minor = release.get('version', {}).get('minor')
releases_by_major.setdefault(major, []).append(release)
Expand All @@ -490,7 +535,7 @@ def set_latest_minor_eol_to_major(releases):
minor_releases.sort(key=lambda r: r.get('version', {}).get('minor', 0))

# Find the corresponding stable release for this major version
stable_release = next((r for r in releases if r['version']['major'] == major and r.get('type') == 'stable'), None)
stable_release = next((r for r in stable_releases if r['version']['major'] == major), None)

# Loop through all minor releases
for i, release in enumerate(minor_releases):
Expand All @@ -505,10 +550,6 @@ def set_latest_minor_eol_to_major(releases):
next_release = minor_releases[i + 1]
release['lifecycle']['eol'] = next_release['lifecycle']['released']





def load_input(filename):
"""Load manual input from a file if it exists."""
try:
Expand Down Expand Up @@ -676,6 +717,11 @@ def parse_arguments():
parser.add_argument('--nightly', action='store_true', help="Generate a nightly release using the current timestamp and git information.")
parser.add_argument('--stable', action='store_true', help="Generate a stable release using the current timestamp and git information.")
parser.add_argument('--patch', action='store_true', help="Generate a patch release using the current timestamp and git information.")
parser.add_argument('--version', type=str, help="Manually specify the version (format: major.minor).")
parser.add_argument('--commit', type=str, help="Manually specify the git commit hash (40 characters).")
parser.add_argument('--date-time-released', type=str, help="Manually specify the release date and time in ISO format (YYYY-MM-DDTHH:MM:SS).")
parser.add_argument('--date-time-extended', type=str, help="Manually specify the extended maintenance date and time in ISO format (YYYY-MM-DDTHH:MM:SS).")
parser.add_argument('--date-time-eol', type=str, help="Manually specify the EOL date and time in ISO format (YYYY-MM-DDTHH:MM:SS).")
parser.add_argument('--input-stdin', action='store_true', help="Process a single input from stdin (JSON data).")
parser.add_argument('--input', action='store_true', help="Process input from --input-file.")
parser.add_argument('--input-file', type=str, default="releases-input.yaml", help="The name of the input file (default: releases-input.yaml).")
Expand Down Expand Up @@ -715,81 +761,67 @@ if __name__ == "__main__":
releases = get_github_releases()

# Variables to store inputs, dev/stable/patch releases and nightly releases
dev_releases = []
input_releases = []
stable_releases = []
patch_releases = []
nightly_releases = []
dev_releases = []
merged_releases = []

# Create initial stable and patch releases if requested
if generate_initial_stable or generate_initial_patch:
stable_releases, patch_releases, latest_minor_versions = create_releases(releases)

# Add stdin input or file input data if provided (existing releases will be overwritten)
if args.input_stdin or args.input:
if args.input_stdin:
input_stable, input_patch, input_nightly, input_dev = load_input_stdin()
elif args.input:
input_stable, input_patch, input_nightly, input_dev = load_input(args.input_file)
stable_releases = merge_input_data(stable_releases, input_stable)
patch_releases = merge_input_data(patch_releases, input_patch)
nightly_releases = merge_input_data(nightly_releases, input_nightly)
dev_releases = merge_input_data(dev_releases, input_dev)

# we define stable releases in input file, therefore this has to be run past defining inputs
# Generate nightly releases if requested (needs stable releases)
if generate_initial_nightly:
nightly_releases = create_nightly_releases(stable_releases)

# Create a development release if requested
if args.dev:
dev_releases = [create_single_release('dev')]
dev_releases = dev_releases + [create_single_release('dev', args)]

# Create a nightly release if requested
if args.nightly:
nightly_releases = [create_single_release('nightly')]
nightly_releases = nightly_releases + [create_single_release('nightly', args)]

# Create a stable release if requested
if args.stable:
stable_releases = [create_single_release('stable')]
stable_releases = stable_releases + [create_single_release('stable', args)]

# Create a patch release if requested
if args.patch:
patch_releases = [create_single_release('patch')]
patch_releases = patch_releases + [create_single_release('patch', args)]

# Create initial stable and patch releases if requested
if generate_initial_stable or generate_initial_patch:
stable_releases, patch_releases, latest_minor_versions = create_releases(releases)
# Set EOL for patch releases based on latest minor versions
set_latest_minor_eol_to_major(stable_releases, patch_releases)

# Merge all releases into a single list
merged_releases = merged_releases + dev_releases + nightly_releases + stable_releases + patch_releases
merged_releases = stable_releases + patch_releases + nightly_releases + dev_releases

# Ensure timestamps for all releases
for release in merged_releases:
ensure_isodate_and_timestamp(release['lifecycle'])

# Set EOL for patch releases based on latest minor versions
set_latest_minor_eol_to_major(merged_releases)
# Validate all releases
validate_all_releases(merged_releases)

# split all releases again
stable_releases = [r for r in merged_releases if r['type'] == 'stable']
patch_releases = [r for r in merged_releases if r['type'] == 'patch']
nightly_releases = [r for r in merged_releases if r['type'] == 'nightly']
dev_releases = [r for r in merged_releases if r['type'] == 'dev']

# Add stdin input or file input data if provided (existing releases will be overwritten)
if args.input_stdin or args.input:
if args.input_stdin:
input_stable, input_patch, input_nightly, input_dev = load_input_stdin()
elif args.input:
input_stable, input_patch, input_nightly, input_dev = load_input(args.input_file)
stable_releases = merge_input_data(stable_releases, input_stable)
patch_releases = merge_input_data(patch_releases, input_patch)
nightly_releases = merge_input_data(nightly_releases, input_nightly)
dev_releases = merge_input_data(dev_releases, input_dev)

# Generate nightly releases if requested (needs stable releases)
if generate_initial_nightly:
start_date_default = datetime(2020, 6, 9)
if len(stable_releases) > 0: # If stable/patch releases were generated
if stable_releases:
first_stable_release = min(stable_releases, key=lambda r: r['lifecycle']['released']['timestamp'])
start_date = datetime.utcfromtimestamp(first_stable_release['lifecycle']['released']['timestamp'])
else:
print("No stable releases found in the generated data. Using default start date.")
start_date = start_date_default
else:
print("No stable/patch releases generated. Using default start date.")
start_date = start_date_default

nightly_releases = create_nightly_releases(stable_releases, start_date)
merged_releases = merged_releases + nightly_releases


# Validate all releases
validate_all_releases(merged_releases)

# Save the release data to disk
if args.no_output_split:
output_file = args.output_file_prefix
Expand Down

0 comments on commit b9d6152

Please sign in to comment.