diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cdaae7f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +# Container image that runs your code +FROM python:3.11-alpine + +# Copies your code file from your action repository to the filesystem path `/` of the container +COPY entrypoint.sh /entrypoint.sh +COPY upload_package.py /upload_package.py + +RUN pip3 install requests +RUN pip3 install urllib3 + +# Code file to execute when the docker container starts up (`entrypoint.sh`) +ENTRYPOINT ["/entrypoint.sh"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..de88db8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 GitHub Actions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac0ca45 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# Github Action Soti Apk Uploader + +## Inputs + +### `soti-api-url`: + +**Required** 'Soti api url' + +### `apk-path`: + +**Required** 'path of Apk' + +### `soti-api-key`: + +**Required** 'Soti api key' + +### `soti-api-secret`: + +**Required** 'Soti api secret' + +### `soti-username`: + +**Required** 'Soti username' + +### `soti-password`: + +**Required** 'Soti password' + + +## Example usage + +```yaml +uses: ZeroGachis/github-action-soti-apk-uploader@main +with: + soti-api-url: 'Soti api url' + apk-path: 'Apk path' + soti-api-key: 'Soti api key' + soti-api-secret: 'Soti api secret' + soti-username: 'Soti username' + soti-password: 'Soti password' +``` diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..23c5107 --- /dev/null +++ b/action.yml @@ -0,0 +1,31 @@ +name: 'Github Action Soti Apk Uploader' +description: 'a Github Action to push an Apk on Soti' +inputs: + soti-api-url: + description: 'Soti api url' + required: true + apk-path: + description: 'apk path' + required: true + soti-api-key: + description: 'Soti api key' + required: true + soti-api-secret: + description: 'Soti api secret' + required: true + soti-username: + description: 'Soti username' + required: true + soti-password: + description: 'Soti password' + required: true +runs: + using: 'docker' + image: 'Dockerfile' + args: + - ${{ inputs.soti-api-url }} + - ${{ inputs.apk-path }} + - ${{ inputs.soti-api-key }} + - ${{ inputs.soti-api-secret }} + - ${{ inputs.soti-username }} + - ${{ inputs.soti-password }} diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..446f83f --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/sh -l + +python /upload_package.py $1 /github/workspace/$2 $3 $4 $5 $6 diff --git a/upload_package.py b/upload_package.py new file mode 100644 index 0000000..96a73d8 --- /dev/null +++ b/upload_package.py @@ -0,0 +1,82 @@ +import argparse +import json +from urllib3.fields import RequestField +from urllib3.filepost import encode_multipart_formdata, choose_boundary +import requests + + +parser = argparse.ArgumentParser("Upload apk on mobi control.") +parser.add_argument("sotiapi", help="Uri soti api endpoint.", type=str) +parser.add_argument("srcfile", help="Apk file path", type=str) +parser.add_argument("client_id", help="Soti api client id", type=str) +parser.add_argument("client_secret", help="Soti api client secret.", type=str) +parser.add_argument("username", help="Mobi control username.", type=str) +parser.add_argument("password", help="Mobi control password.", type=str) +args = parser.parse_args() + +sotiapi = args.sotiapi +srcfile = args.srcfile +client_id = args.client_id +client_secret = args.client_secret +username = args.username +password = args.password + + +def encode_multipart_related(fields, boundary=None): + if boundary is None: + boundary = choose_boundary() + + body, _ = encode_multipart_formdata(fields, boundary) + content_type = str("multipart/related; boundary=%s" % boundary) + + return body, content_type + + +def encode_media_related(metadata, media, media_content_type): + rf1 = RequestField( + name="metadata", + data=json.dumps(metadata), + headers={"Content-Type": "application/vnd.android.application.metadata+json"}, + ) + rf2 = RequestField( + name="apk", + data=media, + headers={ + "Content-Type": media_content_type, + "Content-Transfer-Encoding": "binary", + }, + ) + return encode_multipart_related([rf1, rf2]) + + +metadata = {"DeviceFamily": "AndroidPlus"} +token = "" + +print("Getting token.\n") +with requests.session() as c: + resp = c.post( + f"{sotiapi}/api/token", + auth=(client_id, client_secret), + data={"grant_type": "password", "username": username, "password": password}, + verify=True, + ) + token = resp.json()["access_token"] + +body, content_type = encode_media_related( + metadata, + open(srcfile, "rb").read(), + "application/vnd.android.application", +) + +print("Upload pakages.\n") +resp = requests.post( + f"{sotiapi}/api/packages", + data=body, + headers={"Content-Type": content_type, "Authorization": f"Bearer {token}"}, + verify=True, +) +print(resp.status_code, "\n") +print("Message: %s" % resp.json()) + +if not (200 <= resp.status_code < 300): + raise Exception("Issue was encountered while uploading APK on SOTI !")