c3lang / c3c

Compiler for the C3 language
https://c3-lang.org
GNU Lesser General Public License v3.0
3.03k stars 183 forks source link

Version management/updater #1421

Open brian-sinquin opened 2 months ago

brian-sinquin commented 2 months ago

Would it not be interesting to have a version manager in order to keep the compiler up-to-date as well as vendor libraries ? Something like juliaup (the Julia version manager).

This could also mean the need of online prebuilt binaries of the compiler for the different platforms, that could be created using CI.

lerno commented 2 months ago

Yes, eventually – but as you noted right now this is a problem as we're just compiling for a subset of the Linux distros for example. And this in turn is because we neither have Docker container for them, nor a build of LLVM/LLD for them. But possibly this could be done piecemeal, starting with Windows.

I also still hope someone will shoulder the task of setting up CI for more Linux distros.

brian-sinquin commented 2 months ago

Eventually one could fetch the last tag version by parsing the JSON at this url : https://api.github.com/repos/c3lang/c3c/releases.

brian-sinquin commented 2 months ago

I've made this script that creates a json file containing some metadata of each versions. It could be launched frequently and the json file could be fetched by the compiler to compare its version to the last release, and in the future, fetch automatically an update. I dont know how this script can be involved in the CI, nor where to store the version database json file (push on the repo?).

#!/usr/bin/python
import urllib.request
import json
import re
import datetime

# May have some unaccuracy if compiler use another date zone than github (UTC) -> at worth 1h error, thats ok to compare releases.
def date_to_timestamp(date):
    return datetime.datetime.strptime(date,'%Y-%m-%dT%H:%M:%SZ').timestamp()

# for the moment major.minor.patch, returns (major, minor, patch, error -> bool)
def split_version(version):

    try:
        split_info = list(re.findall(r"([0-9]).([0-9]).?([0-9]*)?", version)[0])
    except: 
        return (0,0,0,False)
    else :
        if split_info[2] == '' : split_info[2] = '0' # if missing patch info
        return tuple(map(int, split_info)) + (True,)

def main():

    repo_url = "https://api.github.com/repos/c3lang/c3c/releases"
    response = urllib.request.urlopen(repo_url).read()

    releases_json = json.loads(response) 
    version_db = dict()

    for r in releases_json:

        # latest is the last committed from master branch, not a version
        if r['tag_name'] == 'latest': continue;

        version = dict()

        # add relevant information that the compiler should see here
        # for example `assets` which contains the download url of the binaries
        version["name"] = r["name"]

        (major, minor, patch, err) = split_version(r['tag_name'])

        if (err == False) :
            print("Error: could not parse version for tag_name :", r['tag_name'])
            continue  

        version["version"] = f"%i.%i.%i"%(major, minor, patch)
        version["major"] = major
        version["minor"] = minor
        version["patch"] = patch

        version["pre_release"] = r["prerelease"]
        version["date"] = r["published_at"]
        version["date_timestamp"] = int(date_to_timestamp(r["published_at"]))
        # create entry
        version_db[r['tag_name']] = version

    with open('version_db.json', 'w') as file:
        json.dump(version_db, file,indent=4)

main()