diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index d71b7e02..461926cf 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -175,7 +175,9 @@ def create_release(token, package): if file is None: error(400, "Missing 'file' in multipart body") - return api_create_zip_release(token, package, data["title"], file) + commit_hash = data.get("commit") + + return api_create_zip_release(token, package, data["title"], file, None, None, "API", commit_hash) else: error(400, "Unknown release-creation method. Specify the method or provide a file.") diff --git a/app/blueprints/api/support.py b/app/blueprints/api/support.py index 0f09b99e..2683637b 100644 --- a/app/blueprints/api/support.py +++ b/app/blueprints/api/support.py @@ -54,13 +54,13 @@ def api_create_vcs_release(token: APIToken, package: Package, title: str, ref: s def api_create_zip_release(token: APIToken, package: Package, title: str, file, - min_v: MinetestRelease = None, max_v: MinetestRelease = None, reason="API"): + min_v: MinetestRelease = None, max_v: MinetestRelease = None, reason="API", commit_hash:str=None): if not token.canOperateOnPackage(package): error(403, "API token does not have access to the package") reason += ", token=" + token.name - rel = guard(do_create_zip_release)(token.owner, package, title, file, min_v, max_v, reason) + rel = guard(do_create_zip_release)(token.owner, package, title, file, min_v, max_v, reason, commit_hash) return jsonify({ "success": True, diff --git a/app/flatpages/help/api.md b/app/flatpages/help/api.md index 95d4f37e..bb78cf41 100644 --- a/app/flatpages/help/api.md +++ b/app/flatpages/help/api.md @@ -14,7 +14,16 @@ If there is an error, the response will be JSON similar to the following with a Successful GET requests will return the resource's information directly as a JSON response. Other successful results will return a dictionary with `success` equaling true, and -often other keys with information. +often other keys with information. For example: + +```js +{ + "success": true, + "release": { + /* same as returned by a GET */ + } +} +``` ## Authentication @@ -117,7 +126,8 @@ Supported query parameters: * `method`: must be `git`. * `ref`: (Optional) git reference, eg: `master`. * For zip upload release creation: - * `file`: multipart file to upload, like ``. + * `file`: multipart file to upload, like ``. + * `commit`: (Optional) Source Git commit hash, for informational purposes. * You can set min and max Minetest Versions [using the content's .conf file](/help/package_config/). * DELETE `/api/packages///releases//` (Delete) * Requires authentication. @@ -136,6 +146,11 @@ curl -X POST https://content.minetest.net/api/packages/username/name/releases/ne -H "Authorization: Bearer YOURTOKEN" \ -F title="My Release" -F file=@path/to/file.zip +# Create release from zip upload with commit hash +curl -X POST https://content.minetest.net/api/packages/username/name/releases/new/ \ + -H "Authorization: Bearer YOURTOKEN" \ + -F title="My Release" -F commit="8ef74deec170a8ce789f6055a59d43876d16a7ea" -F file=@path/to/file.zip + # Delete release curl -X DELETE https://content.minetest.net/api/packages/username/name/releases/3/ \ -H "Authorization: Bearer YOURTOKEN" @@ -169,7 +184,7 @@ curl -X DELETE https://content.minetest.net/api/packages/username/name/releases/ Examples: ```bash -# Create screenshots +# Create screenshot curl -X POST https://content.minetest.net/api/packages/username/name/screenshots/new/ \ -H "Authorization: Bearer YOURTOKEN" \ -F title="My Release" -F file=@path/to/screnshot.png diff --git a/app/logic/releases.py b/app/logic/releases.py index 7190d1b4..7b1e3c45 100644 --- a/app/logic/releases.py +++ b/app/logic/releases.py @@ -15,7 +15,7 @@ # along with this program. If not, see . -import datetime +import datetime, re from celery import uuid @@ -63,9 +63,15 @@ def do_create_vcs_release(user: User, package: Package, title: str, ref: str, def do_create_zip_release(user: User, package: Package, title: str, file, - min_v: MinetestRelease = None, max_v: MinetestRelease = None, reason: str = None): + min_v: MinetestRelease = None, max_v: MinetestRelease = None, reason: str = None, + commit_hash: str = None): check_can_create_release(user, package) + if commit_hash: + commit_hash = commit_hash.lower() + if not (len(commit_hash) == 40 and re.match(r"^[0-9a-f]+$", commit_hash)): + raise LogicError(400, "Invalid commit hash; it must be a 40 character long base16 string") + uploaded_url, uploaded_path = upload_file(file, "zip", "a zip file") rel = PackageRelease() @@ -73,6 +79,7 @@ def do_create_zip_release(user: User, package: Package, title: str, file, rel.title = title rel.url = uploaded_url rel.task_id = uuid() + rel.commit_hash = commit_hash rel.min_rel = min_v rel.max_rel = max_v db.session.add(rel)