Skip to content

Commit

Permalink
Merge pull request #128 from vardhaman22/auto-add-new-docker-versions
Browse files Browse the repository at this point in the history
added automation to raise PR for new docker versions
  • Loading branch information
kinarashah authored Apr 11, 2024
2 parents 75e5d20 + f2e83de commit 33fd70d
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 0 deletions.
85 changes: 85 additions & 0 deletions .github/workflows/add_new_versions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Add New Docker Versions

on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 3"


permissions:
contents: write
pull-requests: write


jobs:
generate_and_raise_pr:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'

- name: Pip
working-directory: ./workflow_scripts
run: pip install -r requirements.txt

- name: Check if new versions available
id: check-versions
run: |
python workflow_scripts/check-for-new-versions.py
env:
EXCLUDED_VERSIONS: "v20.10.x,v23.0.x"

- name: check if the PR exist
if: ${{ env.PR_TITLE != '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_TITLE: ${{env.PR_TITLE}}
run: |
EXISTING_PR=$(gh pr list --limit 1500 --json title,url | jq --arg title "${PR_TITLE}" -r '.[] | select(.title==$title) | .url')
if [ -n "${EXISTING_PR}" ]; then
echo "pr_exist=true" >> $GITHUB_ENV
echo "Pull request already exists: ${EXISTING_PR}" >> $GITHUB_STEP_SUMMARY
else
echo "pr_exist=false" >> $GITHUB_ENV
fi
- name: generate files for new docker version
if: ${{ env.pr_exist == 'false' && env.PR_TITLE != '' }}
env:
NEW_VERSIONS: ${{ env.NEW_VERSIONS }}
run: |
python workflow_scripts/gen-new-version-files.py
- name: Create branch, commit and push
if: ${{ env.pr_exist == 'false' && env.PR_TITLE != '' }}
id: branch
env:
NEW_VERSIONS: ${{ env.NEW_VERSIONS }}
run: |
BRANCH="gha-add-tag-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
echo "branch=${BRANCH}" >> $GITHUB_OUTPUT
git config user.name github-actions
git config user.email [email protected]
git checkout -b "$BRANCH"
git add .
git commit -m "added docker ${NEW_VERSIONS}"
git push origin "$BRANCH"
- name: Create Pull Request
if: ${{ env.pr_exist == 'false' && env.PR_TITLE != '' }}
id: cpr
env:
SOURCE_BRANCH: ${{ steps.branch.outputs.branch }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_TITLE: ${{env.PR_TITLE}}
PR_BODY: autogenerated PR to add docker ${{env.NEW_VERSIONS}}
run: |
PR_TITLE=$(echo "$PR_TITLE" | cut -c -256)
CREATED_PR=$(gh pr create --title "${PR_TITLE}" --body "${PR_BODY}" --label "status/auto-created" --base "${GITHUB_REF_NAME}" --head "${SOURCE_BRANCH}")
echo "Created pull request: ${CREATED_PR}" >> $GITHUB_STEP_SUMMARY
87 changes: 87 additions & 0 deletions workflow_scripts/check-for-new-versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import os
import subprocess
import requests

# Constants
DIST_FOLDER = './dist'
EXCLUDED_VERSIONS = os.environ.get('EXCLUDED_VERSIONS', 'v20.10.x,v23.0.x')

def get_excluded_version_patterns(excluded_ver_str):
excluded_ver_list = excluded_ver_str.split(',')
excluded_patterns = []
for ver in excluded_ver_list:
ver_parts = ver.split('.')
if len(ver_parts) == 3:
if ver_parts[1] == 'x':
excluded_patterns.append(ver_parts[0])
elif ver_parts[2] == 'x':
excluded_patterns.append(ver_parts[0] + '.'+ ver_parts[1])
else:
excluded_patterns.append(ver)
return excluded_patterns


def is_excluded_version(excluded_patterns,version):
for pattern in excluded_patterns:
if version.startswith(pattern):
return True
return False

def get_existing_versions(files_dir):
existing_versions = set()
for file in os.listdir(files_dir):
if file.endswith('.sh') and file.count('.') == 3:
existing_versions.add('v' + file[:-3])
return existing_versions

def fetch_ten_latest_github_releases(owner, repo):
url = f"https://api.github.com/repos/{owner}/{repo}/releases"
try:
response = requests.get(url)
response.raise_for_status() # Raise exception for bad status codes
releases = [release for release in response.json() if not release.get('prerelease')]
return sorted(releases, key=lambda x: x['created_at'], reverse=True)[:10]
except requests.exceptions.RequestException as e:
print(f"Failed to fetch releases: {e}")
return None

def get_version_tuple(version):
if version.startswith('v'):
version = version[1:]
return tuple(map(int, version.split('.')))

def main():
excluded_ver_patterns = get_excluded_version_patterns(EXCLUDED_VERSIONS)
existing_versions = get_existing_versions(DIST_FOLDER)
owner = "moby"
repo = "moby"
ten_latest_releases = fetch_ten_latest_github_releases(owner, repo)
ten_latest_versions = [release['tag_name'] for release in ten_latest_releases]
print("Ten latest versions: ",ten_latest_versions)

new_versions = set(ten_latest_versions) - existing_versions
new_versions = list(filter(lambda ver: not is_excluded_version(excluded_ver_patterns,ver),new_versions))

sorted_new_versions = sorted(new_versions,key=get_version_tuple)
print('New versions: ',sorted_new_versions)

versions_string = ",".join(sorted_new_versions)
PR_TITLE = ""

if versions_string != "":
PR_TITLE = "[Auto] Add docker " + versions_string
print('PR Title: ', PR_TITLE)

env_file = os.getenv('GITHUB_ENV')

if env_file:
with open(env_file, "a") as envfile:
envfile.write("PR_TITLE="+PR_TITLE+"\n")
envfile.write("NEW_VERSIONS="+versions_string+"\n")
else:
exit(1)



if __name__ == "__main__":
main()
100 changes: 100 additions & 0 deletions workflow_scripts/gen-new-version-files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import os
import subprocess
import requests

# Constants
DIST_FOLDER = './dist'
NEW_VERSIONS = os.environ.get("NEW_VERSIONS","")

if NEW_VERSIONS == "":
print("no new versions available, NEW_VERSIONS env variable is empty")
exit(1)

def get_max_version(ver1, ver2):
if ver1.startswith('v'):
ver1 = ver1[1:]
if ver2.startswith('v'):
ver2 = ver2[1:]

ver1_tuple = tuple(map(int, ver1.split('.')))
ver2_tuple = tuple(map(int, ver2.split('.')))
if ver1 > ver2:
return ver1
return ver2

def format_version(v):
if v.startswith('v'):
return v[1:]
return v

def get_last_added_version(files_dir):
max_modification_time = 0.0
last_added_version = ""
for file in os.listdir(files_dir):
if file.endswith('.sh') and file.count('.') == 3:
file_path = os.path.join(files_dir, file)
modification_time = os.path.getmtime(file_path)
file_version = 'v' + file[:-3]
if modification_time > max_modification_time:
max_modification_time = modification_time
last_added_version = file_version
elif modification_time == max_modification_time:
if last_added_version == "":
last_added_version = file_version
else:
last_added_version = get_max_version(last_added_version,file_version)

return last_added_version

def generate_diffs(prev_version, current_version):
print("executing add-new-version-script with PREVIOUS_ADD_DOCKER_VERSION: ",prev_version,
" ADD_DOCKER_VERSION",current_version)
add_new_version_script_path = "./scripts/add-new-version"
env_vars = {"PREVIOUS_ADD_DOCKER_VERSION": prev_version, "ADD_DOCKER_VERSION": current_version}
subprocess.run(["bash", add_new_version_script_path], check=True, env=env_vars)

# it will return a dictonary with key set to major.minor of a version and the
# value will be the greatest version for that major minor combination
def get_version_dict(versions):
version_dict = {}

for version in versions:
version_parts = version.split('.')
major_minor = version_parts[0] + '.' + version_parts[1]

if major_minor in version_dict:
current_version = tuple(map(int, version_parts[2]))
max_version = tuple(map(int, version_dict[major_minor].split('.')[2]))
if current_version > max_version:
version_dict[major_minor] = version
else:
version_dict[major_minor] = version

return version_dict

def main():

last_added_version = get_last_added_version(DIST_FOLDER)
print("Last added version:",last_added_version)

new_versions = NEW_VERSIONS.split(',')
formatted_new_versions = list(map(format_version,new_versions))
print("Formatted new versions: ", formatted_new_versions)

for version in formatted_new_versions:
generate_diffs(last_added_version, version)

versions_string = ",".join(new_versions)

print("running generate script")
subprocess.run(["bash", "./scripts/generate"], check=True)

version_dict = get_version_dict(formatted_new_versions)
print("version dictionary for symlink: ",version_dict)

for major_minor,version in version_dict.items():
subprocess.call(['rm',f"{DIST_FOLDER}/{major_minor}.sh"])
os.symlink(f"{version}.sh",f"{DIST_FOLDER}/{major_minor}.sh")

if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions workflow_scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Requests==2.31.0

0 comments on commit 33fd70d

Please sign in to comment.