diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b12176d7..261dc125 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,15 +27,15 @@ jobs: strategy: matrix: os-name: [ ubuntu-latest, ubuntu-18.04, macOS-latest, windows-latest ] - python-version: [ 3.8 ] + python-version: [ 3.9 ] # needs: [ install-test ] steps: # checkout commit - name: Checkout commit - uses: actions/checkout@v1 + uses: actions/checkout@v2 # install python - name: Install python - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} architecture: "x64" @@ -48,6 +48,28 @@ jobs: run: | python ./resources/ci/common/install.py pip install pyinstaller + # get parent directory + - name: Get Repo Name + uses: mad9000/actions-find-and-replace-string@1 + id: repoName + with: + source: ${{ github.repository }} + find: '${{ github.repository_owner }}/' + replace: '' + - name: Get Parent Directory Path (!Windows) + uses: mad9000/actions-find-and-replace-string@1 + id: parentDirNotWin + with: + source: ${{ github.workspace }} + find: '${{ steps.repoName.outputs.value }}/${{ steps.repoName.outputs.value }}' + replace: ${{ steps.repoName.outputs.value }} + - name: Get Parent Directory Path (Windows) + uses: mad9000/actions-find-and-replace-string@1 + id: parentDir + with: + source: ${{ steps.parentDirNotWin.outputs.value }} + find: '${{ steps.repoName.outputs.value }}\${{ steps.repoName.outputs.value }}' + replace: ${{ steps.repoName.outputs.value }} # try to get UPX - name: Get UPX env: @@ -70,10 +92,10 @@ jobs: python ./resources/ci/common/prepare_binary.py # upload binary artifacts for later step - name: Upload Binary Artifacts - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: binaries-${{ matrix.os-name }} - path: ../artifact + path: ${{ steps.parentDir.outputs.value }}/artifact # Install & Preparing Release # Set up environment @@ -87,18 +109,18 @@ jobs: # os & python versions strategy: matrix: - # install/release on not xenial + # install/release on not bionic os-name: [ ubuntu-latest, ubuntu-18.04, macOS-latest, windows-latest ] - python-version: [ 3.8 ] + python-version: [ 3.9 ] needs: [ install-build ] steps: # checkout commit - name: Checkout commit - uses: actions/checkout@v1 + uses: actions/checkout@v2 # install python - name: Install Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} architecture: "x64" @@ -110,9 +132,31 @@ jobs: OS_NAME: ${{ matrix.os-name }} run: | python ./resources/ci/common/install.py + # get parent directory + - name: Get Repo Name + uses: mad9000/actions-find-and-replace-string@1 + id: repoName + with: + source: ${{ github.repository }} + find: '${{ github.repository_owner }}/' + replace: '' + - name: Get Parent Directory Path (!Windows) + uses: mad9000/actions-find-and-replace-string@1 + id: parentDirNotWin + with: + source: ${{ github.workspace }} + find: '${{ steps.repoName.outputs.value }}/${{ steps.repoName.outputs.value }}' + replace: ${{ steps.repoName.outputs.value }} + - name: Get Parent Directory Path (Windows) + uses: mad9000/actions-find-and-replace-string@1 + id: parentDir + with: + source: ${{ steps.parentDirNotWin.outputs.value }} + find: '${{ steps.repoName.outputs.value }}\${{ steps.repoName.outputs.value }}' + replace: ${{ steps.repoName.outputs.value }} # download binary artifact - name: Download Binary Artifact - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: binaries-${{ matrix.os-name }} path: ./ @@ -126,22 +170,22 @@ jobs: python ./resources/ci/common/prepare_release.py # upload appversion artifact for later step - name: Upload AppVersion Artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: appversion-${{ matrix.os-name }} path: ./resources/app/meta/manifests/app_version.txt # upload archive artifact for later step - name: Upload Archive Artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: archive-${{ matrix.os-name }} - path: ../deploy + path: ${{ steps.parentDir.outputs.value }}/deploy # Deploy to GitHub Releases # Release Name: ALttPDoorRandomizer v${GITHUB_TAG} # Release Body: Inline content of RELEASENOTES.md # Release Body: Fallback to URL to RELEASENOTES.md - # Release Files: ../deploy + # Release Files: ${{ steps.parentDir.outputs.value }}/deploy deploy-release: name: Deploy GHReleases runs-on: ${{ matrix.os-name }} @@ -150,42 +194,64 @@ jobs: # os & python versions strategy: matrix: - # release only on focal/bionic + # release only on focal os-name: [ ubuntu-latest ] - python-version: [ 3.8 ] + python-version: [ 3.9 ] needs: [ install-prepare-release ] steps: # checkout commit - name: Checkout commit - uses: actions/checkout@v1 + uses: actions/checkout@v2 + # get parent directory + - name: Get Repo Name + uses: mad9000/actions-find-and-replace-string@1 + id: repoName + with: + source: ${{ github.repository }} + find: '${{ github.repository_owner }}/' + replace: '' + - name: Get Parent Directory Path (!Windows) + uses: mad9000/actions-find-and-replace-string@1 + id: parentDirNotWin + with: + source: ${{ github.workspace }} + find: '${{ steps.repoName.outputs.value }}/${{ steps.repoName.outputs.value }}' + replace: ${{ steps.repoName.outputs.value }} + - name: Get Parent Directory Path (Windows) + uses: mad9000/actions-find-and-replace-string@1 + id: parentDir + with: + source: ${{ steps.parentDirNotWin.outputs.value }} + find: '${{ steps.repoName.outputs.value }}\${{ steps.repoName.outputs.value }}' + replace: ${{ steps.repoName.outputs.value }} - name: Install Dependencies via pip run: | python -m pip install pytz requests # download appversion artifact - name: Download AppVersion Artifact - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: appversion-${{ matrix.os-name }} - path: ../build + path: ${{ steps.parentDir.outputs.value }}/build # download ubuntu archive artifact - name: Download Ubuntu Archive Artifact - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: archive-ubuntu-latest - path: ../deploy/linux + path: ${{ steps.parentDir.outputs.value }}/deploy/linux # download macos archive artifact - name: Download MacOS Archive Artifact - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: archive-macOS-latest - path: ../deploy/macos + path: ${{ steps.parentDir.outputs.value }}/deploy/macos # download windows archive artifact - name: Download Windows Archive Artifact - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: archive-windows-latest - path: ../deploy/windows + path: ${{ steps.parentDir.outputs.value }}/deploy/windows # debug info - name: Debug Info id: debug_info @@ -199,44 +265,35 @@ jobs: RELEASE_NAME="ALttPDoorRandomizer ${GITHUB_TAG}" echo "Release Name: ${RELEASE_NAME}" echo "Git Tag: ${GITHUB_TAG}" - # read releasenotes - - name: Read RELEASENOTES - id: release_notes - run: | - body="$(cat RELEASENOTES.md)" - body="${body//'%'/'%25'}" - body="${body//$'\n'/'%0A'}" - body="${body//$'\r'/'%0D'}" - echo "::set-output name=body::$body" # create a pre/release - name: Create a Pre/Release id: create_release - uses: actions/create-release@master + uses: actions/create-release@v1.1.4 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: v${{ steps.debug_info.outputs.github_tag }} release_name: ALttPDoorRandomizer v${{ steps.debug_info.outputs.github_tag }} - body: ${{ steps.release_notes.outputs.body }} + body_path: RELEASENOTES.md draft: true prerelease: true if: contains(github.ref, 'master') || contains(github.ref, 'stable') || contains(github.ref, 'dev') || contains(github.ref, 'DoorRelease') # upload linux archive asset - name: Upload Linux Archive Asset id: upload-linux-asset - uses: actions/upload-release-asset@v1.0.1 + uses: actions/upload-release-asset@v1.0.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ../deploy/linux/ALttPDoorRandomizer.tar.gz - asset_name: ALttPDoorRandomizer-${{ steps.debug_info.outputs.github_tag }}-linux-bionic.tar.gz + asset_name: ALttPDoorRandomizer-${{ steps.debug_info.outputs.github_tag }}-linux-focal.tar.gz asset_content_type: application/gzip if: contains(github.ref, 'master') || contains(github.ref, 'stable') || contains(github.ref, 'dev') || contains(github.ref, 'DoorRelease') # upload macos archive asset - name: Upload MacOS Archive Asset id: upload-macos-asset - uses: actions/upload-release-asset@v1.0.1 + uses: actions/upload-release-asset@v1.0.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -248,7 +305,7 @@ jobs: # upload windows archive asset - name: Upload Windows Archive Asset id: upload-windows-asset - uses: actions/upload-release-asset@v1.0.1 + uses: actions/upload-release-asset@v1.0.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/docs/BUILDING.md b/docs/BUILDING.md index fd0233f0..298230ed 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -1,13 +1,19 @@ # Running from source -1. Get [python](http://python.org/downloads) -1. Get the [Door Randomizer Unstable source code](https://github.com/Aerinon/ALttPDoorRandomizer/archive/DoorDevUnstable.zip) -1. Install Platform-specific dependencies -1. Run `DoorRandomizer.py` for command-line script -1. Run `Gui.py` for user interface +|Instruction|Image| +|-----------|-----| +|Get [python](http://python.org/downloads)|![Get python](https://raw.githubusercontent.com/miketrethewey/ALttPDoorRandomizer/DoorDevUnstable/docs/images/python.png) +|Get the [Door Randomizer Unstable source code](https://github.com/Aerinon/ALttPDoorRandomizer/archive/DoorDevUnstable.zip)|![Get source code](https://raw.githubusercontent.com/miketrethewey/ALttPDoorRandomizer/DoorDevUnstable/docs/images/sourcecode.png) +|Install Platform-specific dependencies (see below)|![Command line](https://raw.githubusercontent.com/miketrethewey/ALttPDoorRandomizer/DoorDevUnstable/docs/images/cmd.png) +|Run `DungeonRandomizer.py` for command-line script|![DungeonRandomizer.py](https://raw.githubusercontent.com/miketrethewey/ALttPDoorRandomizer/DoorDevUnstable/docs/images/py-dungeonrandomizer.png) +|Run `Gui.py` for user interface|![Gui.py](https://raw.githubusercontent.com/miketrethewey/ALttPDoorRandomizer/DoorDevUnstable/docs/images/py-gui.png) ## Platform-specific dependencies -### Windows - -* Run `resources/ci/common/local_install.py` +|Platform|Command line|Image| +| :----: |------------|-----| +|Windows |`resources/ci/common/local_install.py`|![Windows](https://raw.githubusercontent.com/miketrethewey/ALttPDoorRandomizer/DoorDevUnstable/docs/images/cli-windows.png) +|`py` Launcher: 3.9 |`resources/ci/common/local_install.py --py 3.9`| +|`py` Launcher: 3.8 |`resources/ci/common/local_install.py --py 3.8`| +|`py` Launcher: 3.7 |`resources/ci/common/local_install.py --py 3.7`| +|`py` Launcher: 3.6 |`resources/ci/common/local_install.py --py 3.6`| diff --git a/docs/images/cli-windows.png b/docs/images/cli-windows.png new file mode 100644 index 00000000..2cb7a092 Binary files /dev/null and b/docs/images/cli-windows.png differ diff --git a/docs/images/cmd.png b/docs/images/cmd.png new file mode 100644 index 00000000..cb2b6973 Binary files /dev/null and b/docs/images/cmd.png differ diff --git a/docs/images/py-dungeonrandomizer.png b/docs/images/py-dungeonrandomizer.png new file mode 100644 index 00000000..f3d8de6a Binary files /dev/null and b/docs/images/py-dungeonrandomizer.png differ diff --git a/docs/images/py-gui.png b/docs/images/py-gui.png new file mode 100644 index 00000000..6d7b3cc9 Binary files /dev/null and b/docs/images/py-gui.png differ diff --git a/docs/images/python.png b/docs/images/python.png new file mode 100644 index 00000000..87bd1a61 Binary files /dev/null and b/docs/images/python.png differ diff --git a/docs/images/sourcecode.png b/docs/images/sourcecode.png new file mode 100644 index 00000000..07acbf7b Binary files /dev/null and b/docs/images/sourcecode.png differ diff --git a/resources/ci/common/common.py b/resources/ci/common/common.py index f2288fe2..b89a266b 100644 --- a/resources/ci/common/common.py +++ b/resources/ci/common/common.py @@ -1,5 +1,7 @@ import os # for env vars import stat # file statistics +import sys # default system info +from my_path import get_py_path global UBUNTU_VERSIONS global DEFAULT_EVENT @@ -44,6 +46,8 @@ def prepare_env(): APP_VERSION = f.readlines()[0].strip() # ci data env["CI_SYSTEM"] = os.getenv("CI_SYSTEM","") + # py data + (env["PYTHON_EXE_PATH"],env["PY_EXE_PATH"],env["PIP_EXE_PATH"]) = get_py_path() # git data env["BRANCH"] = os.getenv("TRAVIS_BRANCH","") env["GITHUB_ACTOR"] = os.getenv("GITHUB_ACTOR","MegaMan.EXE") @@ -75,10 +79,19 @@ def prepare_env(): env["BUILD_NUMBER"] = os.getenv("TRAVIS_BUILD_NUMBER",env["GITHUB_RUN_NUMBER"]) GITHUB_TAG = os.getenv("TRAVIS_TAG",os.getenv("GITHUB_TAG","")) - OS_NAME = os.getenv("TRAVIS_OS_NAME",os.getenv("OS_NAME","")).replace("macOS","osx") + OS_NAME = os.getenv("TRAVIS_OS_NAME",os.getenv("OS_NAME",sys.platform)).replace("macOS","osx") OS_DIST = os.getenv("TRAVIS_DIST","notset") OS_VERSION = "" + if "win32" in OS_NAME or \ + "cygwin" in OS_NAME or \ + "msys" in OS_NAME: + OS_NAME = "windows" + elif "darwin" in OS_NAME: + OS_NAME = "osx" + elif "linux2" in OS_NAME: + OS_NAME = "linux" + if '-' in OS_NAME: OS_VERSION = OS_NAME[OS_NAME.find('-')+1:] OS_NAME = OS_NAME[:OS_NAME.find('-')] diff --git a/resources/ci/common/get_get_pip.py b/resources/ci/common/get_get_pip.py index 9b69930d..a0e127ba 100644 --- a/resources/ci/common/get_get_pip.py +++ b/resources/ci/common/get_get_pip.py @@ -1,39 +1,63 @@ import common +import argparse +import os import urllib.request, ssl import subprocess # do stuff at the shell level env = common.prepare_env() -def get_get_pip(): - print("Getting pip getter!") - #make the request! - url = "https://bootstrap.pypa.io/get-pip.py" - context = ssl._create_unverified_context() - req = urllib.request.urlopen(url, context=context) - got_pip = req.read().decode("utf-8") +def get_get_pip(PY_VERSION): + try: + import pip + except ImportError: + print("Getting pip getter!") + #make the request! + url = "https://bootstrap.pypa.io/get-pip.py" + context = ssl._create_unverified_context() + req = urllib.request.urlopen(url, context=context) + got_pip = req.read().decode("utf-8") - with open("get-pip.py", "w") as g: - req = urllib.request.Request( - url, - data=None, - headers={ - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" - } - ) - req = urllib.request.urlopen(req, context=context) - data = req.read().decode("utf-8") - g.write(data) + with open("get-pip.py", "w") as g: + req = urllib.request.Request( + url, + data=None, + headers={ + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" + } + ) + req = urllib.request.urlopen(req, context=context) + data = req.read().decode("utf-8") + g.write(data) - # get executables - # python - # linux/windows: python - # macosx: python3 - PYTHON_EXECUTABLE = "python3" if "osx" in env["OS_NAME"] else "python" - print("Getting pip!") - subprocess.check_call([PYTHON_EXECUTABLE,"get-pip.py"]) + # get executables + # python + # linux/windows: python + # macosx: python3 + PYTHON_EXECUTABLE = "python3" if "osx" in env["OS_NAME"] else "python" + if PY_VERSION == None: + PY_VERSION = 0 + + if float(PY_VERSION) > 0: + PYTHON_EXECUTABLE = "py" + + print("Getting pip!") + args = [ + env["PYTHON_EXE_PATH"] + PYTHON_EXECUTABLE, + '-' + str(PY_VERSION), + "get-pip.py" + ] + if PY_VERSION == 0: + del args[1] + subprocess.check_call(args) if __name__ == "__main__": - try: - import pip - except ImportError: - get_get_pip() + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--py', default=0) + command_line_args = parser.parse_args() + PY_VERSION = vars(command_line_args)["py"] + + try: + import pip + print("pip is installed") + except ImportError: + get_get_pip(PY_VERSION) diff --git a/resources/ci/common/install.py b/resources/ci/common/install.py index 70d10202..5874d0dd 100644 --- a/resources/ci/common/install.py +++ b/resources/ci/common/install.py @@ -1,9 +1,14 @@ import common +import argparse +import os +import platform import subprocess # do stuff at the shell level env = common.prepare_env() -def run_install(): +pip_requirements = os.path.join(".","resources","app","meta","manifests","pip_requirements.txt") + +def run_install(PY_VERSION,USER): # get executables # python # linux/windows: python @@ -11,20 +16,79 @@ def run_install(): # pip # linux/macosx: pip3 # windows: pip + PYTHON_PATH = env["PYTHON_EXE_PATH"] PYTHON_EXECUTABLE = "python3" if "osx" in env["OS_NAME"] else "python" + PIP_PATH = env["PIP_EXE_PATH"] PIP_EXECUTABLE = "pip" if "windows" in env["OS_NAME"] else "pip3" PIP_EXECUTABLE = "pip" if "osx" in env["OS_NAME"] and "actions" in env["CI_SYSTEM"] else PIP_EXECUTABLE - # upgrade pip - subprocess.check_call([PYTHON_EXECUTABLE,"-m","pip","install","--upgrade","pip"]) + if PY_VERSION == None: + PY_VERSION = 0 + if USER == None: + USER = False + + if float(PY_VERSION) > 0: + PYTHON_EXECUTABLE = "py" + PYTHON_PATH = env["PY_EXE_PATH"] + print("Installing to Python %.1f via Py Launcher" % float(PY_VERSION)) + else: + print("Installing to Python %s" % platform.python_version()) + print("Installing packages at %s level" % ("User" if USER else "Global")) + + print() + print("Upgrading pip-") + # upgrade pip + args = [ + PYTHON_PATH + PYTHON_EXECUTABLE, + '-' + str(PY_VERSION), + "-m", + "pip", + "install", + "--upgrade", + "--user", + "pip" + ] + if not USER: + args.remove("--user") + if PY_VERSION == 0: + del args[1] + subprocess.check_call(args) - # pip version - subprocess.check_call([PIP_EXECUTABLE,"--version"]) # if pip3, install wheel if PIP_EXECUTABLE == "pip3": - subprocess.check_call([PIP_EXECUTABLE,"install","-U","wheel"]) + print("Installing Wheel!") + args = [ + PIP_PATH + PIP_EXECUTABLE, + "install", + "--user", + "-U", + "wheel" + ] + if not USER: + args.remove("--user") + subprocess.check_call(args) + + print() # install listed dependencies - subprocess.check_call([PIP_EXECUTABLE,"install","-r","./resources/app/meta/manifests/pip_requirements.txt"]) + print("Installing dependencies") + print("-----------------------") + args = [ + PIP_PATH + PIP_EXECUTABLE, + "install", + "--user", + "-r", + pip_requirements + ] + if not USER: + args.remove("--user") + subprocess.check_call(args) if __name__ == "__main__": - run_install() + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--py', default=0) + parser.add_argument('--user', default=False, action="store_true") + command_line_args = parser.parse_args() + PY_VERSION = vars(command_line_args)["py"] + USER = vars(command_line_args)["user"] + + run_install(PY_VERSION,USER) diff --git a/resources/ci/common/local_install.py b/resources/ci/common/local_install.py index 8cde8348..02cc25a5 100644 --- a/resources/ci/common/local_install.py +++ b/resources/ci/common/local_install.py @@ -1,8 +1,17 @@ import install import get_get_pip +import argparse + +parser = argparse.ArgumentParser(add_help=False) +parser.add_argument('--py', default=0) +parser.add_argument('--user', default=False, action="store_true") +command_line_args = parser.parse_args() +PY_VERSION = vars(command_line_args)["py"] +USER = vars(command_line_args)["user"] + # get & install pip -get_get_pip.get_get_pip() +get_get_pip.get_get_pip(PY_VERSION) # run installer -install.run_install() +install.run_install(PY_VERSION,USER) diff --git a/resources/ci/common/my_path.py b/resources/ci/common/my_path.py new file mode 100644 index 00000000..7d91f15e --- /dev/null +++ b/resources/ci/common/my_path.py @@ -0,0 +1,33 @@ +import os +import sys + +def get_py_path(): + user_paths = os.environ["PATH"].split(os.pathsep) + (python,py) = ("","") + + for path in user_paths: + parts = path.split(os.sep) + part = parts[len(parts) - 1].lower() + if ("python" in part) and ('.' not in part): + path.replace(os.sep,os.sep + os.sep) + if path not in user_paths: + py = path + + for path in sys.path: + parts = path.split(os.sep) + part = parts[len(parts) - 1].lower() + if ("python" in part) and ('.' not in part): + path.replace(os.sep,os.sep + os.sep) + if path not in user_paths: + python = path + + paths = ( + os.path.join(python,"") if python != "" else "", + os.path.join(py,"") if py != "" else "", + os.path.join(python,"Scripts","") if python != "" else "" + ) + # print(paths) + return paths + +if __name__ == "__main__": + get_py_path()