diff --git a/.ci/deploy.sh b/.ci/deploy.sh index 40a87e0f..2e8bff78 100755 --- a/.ci/deploy.sh +++ b/.ci/deploy.sh @@ -1,98 +1,33 @@ #!/bin/bash set -e # Exit with nonzero exit code if anything fails -SOURCE_BRANCH="master" -TARGET_BRANCH="files" - function doCompile { - echo "Running script..." - python3 -m magic_spoiler + echo "Running script..." + python3 -m magic_spoiler } # Pull requests and commits to other branches shouldn't try to deploy, just build to verify -if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then - echo "Skipping deploy; just doing a build." - # Run our compile script and let user know in logs - doCompile - exit 0 -fi - -# Save some useful information -REPO=`git config remote.origin.url` -SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:} -SHA=`git rev-parse --verify HEAD` - -# Clone the existing gh-pages for this repo into out/ -# Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply) -rm -rf out/ -git clone $REPO out --single-branch --branch $TARGET_BRANCH -cd out -git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH -cd .. - -rm -rf out/**/* || exit 0 -# Run our compile script and let user know in logs -doCompile - -echo TRAVIS_PULL_REQUEST ${TRAVIS_PULL_REQUEST} -echo TRAVIS_SECURE_ENV_VARS ${TRAVIS_SECURE_ENV_VARS} -echo TRAVIS_EVENT_TYPE ${TRAVIS_EVENT_TYPE} - -# Don't push to our branch for PRs. -#if [ "${ghToken:-false}" != "false" ]; then -# doCompile -#else -# doCompile -# exit 0 -#fi - -# Now let's go have some fun with the cloned repo -cd out -ls -git config user.name "Travis CI" -git config user.email "$COMMIT_AUTHOR_EMAIL" - -# If there are no changes to the compiled out (e.g. this is a README update) then just bail. -#if git diff --quiet; then -# echo "No changes to the output on this push; exiting." -# exit 0 -#fi - -# Commit the "changes", i.e. the new version. -# The delta will show diffs between new and old versions. -# Only commit if more than one line has been changed (datetime in spoiler.xml) -CHANGED_FILES=`git ls-files -m | wc -l` -ONLYDATECHANGE=true -if [[ $CHANGED_FILES -eq 1 ]]; then - for CHANGED_FILE in `git diff --name-only`; do - if ! [[ $CHANGED_FILE =~ "spoiler.xml" ]]; then - ONLYDATECHANGE=false - fi - done -else - ONLYDATECHANGE=false -fi - -if [[ $ONLYDATECHANGE == false ]]; then - # We don't want the AllSets... waste of space - git add -A . - git commit -m "Travis Deploy: ${SHA}" -else - echo "Only date in spoiler.xml changed, not committing" +if [[ ! -d $OUTPUT_PATH ]]; then + mkdir "$OUTPUT_PATH" + echo "Skipping deploy; just doing a build." + # Run our compile script and let user know in logs + doCompile exit 0 fi -# Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc -ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" -ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" -ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR} -ENCRYPTED_IV=${!ENCRYPTED_IV_VAR} -openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../.ci/deploy_key.enc -out ../deploy_key -d -chmod 600 ../deploy_key -eval `ssh-agent -s` -ssh-add ../deploy_key +# Run our compile script and exit gracefully if there are no updates +if ! doCompile; then + echo ":warning:No changes!" + exit 0 +fi -# Now that we're all set up, we can push. -git push $SSH_REPO $TARGET_BRANCH +cd "$OUTPUT_PATH" +git config user.name github-actions +git config user.email github-actions@github.com -ssh-agent -k +# We don't want the AllSets... waste of space +git add -A . +git commit -m "Deploy: ${GITHUB_SHA}" + +# push using built-in token +git push diff --git a/.ci/deploy_key.enc b/.ci/deploy_key.enc deleted file mode 100644 index 7ab20945..00000000 Binary files a/.ci/deploy_key.enc and /dev/null differ diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..b1ba14bb --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,47 @@ +name: Deploy + +on: + push: + branches: + - master + paths-ignore: + - '**.md' + pull_request: + branches: + - master + paths-ignore: + - '**.md' + schedule: + # every 6 hours = 4 times a day + - cron: '0 */6 * * *' + +jobs: + deploy: + runs-on: ubuntu-latest + + env: + OUTPUT_PATH: out + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Checkout output branch + if: github.ref == 'refs/heads/master' + uses: actions/checkout@v2 + with: + ref: files + fetch-depth: 0 + path: ${{env.OUTPUT_PATH}} + + - name: Install requirements using pip + shell: bash + env: + CFLAGS: '-O0' + run: | + python3 -m pip install --upgrade pip setuptools + python3 -m pip install --requirement requirements.txt + + - name: Deploy + shell: bash + run: ./.ci/deploy.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 57204c6a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,64 +0,0 @@ -language: python -python: - - "3.6" - -cache: pip # enable cache for "$HOME/.cache/pip" directory - -env: - global: - - ENCRYPTION_LABEL: ec68c19ba263 - - -before_install: - - export CFLAGS=-O0 # considerably speed-up build time for pip packages (especially lxml), optimizations doesn't matter for ci - -install: - - pip install -r requirements.txt - -script: bash ./.ci/deploy.sh - - -## Builds for pull requests skip the deployment step altogether -#deploy: -## Continious deployment of most recent spoiler.xml -# - provider: releases -# api_key: -# secure: Bin220gU9Re176T/1bIaX/rhGB+uEaw13aoB2/ir0ePHQB0ihasEJcsgmlN8kz93KSN6vp4y2HwMLnz3t7Pn0amTV8QVL/AlOOzjbq8m/1kYTbXdPlYnMsosZPVFLHRan4LEGFsovRia6LO4p9fqC8BDgQl89W/88PlYAMWzao5jTyKKHp8o+sioYhKj9D+86lxLYspQ+6SN0HOCnF2MZ/vZtxbY32ituswAc/sJK1MtZ/PExoMe1nSI2iKCaatXyKA+FVCUNLHRAu4LgB1GfJCLpmlPbvjud8A6WAKNF6poNCvFck+Ox56tt4bw3ggR5W9kTEhvX74l6AEeC7Qz6bHjh1CEngrqFjyaHy25CcygWgagf0DUsvyGRS0RqEx4bz9psD09d+oWihdkJMfa5kRzXtVQD8sxDgsBqEz/DjsMIlf/L5ISSa7lAYiqq65ELpezBFOlvEZ9avOYLcZc7m5/5ZhtcA4HPSqzfn2nhkPpeggBKufMdyc8JIDkvs/JlFsNu46QVvugjbdGvtb4SlQK310py0TOA6nYt7WntDhX3SukKAeh6oHjZaL5aeoSBhnlQRgJfDBqI3+7anLatD30uEKCMp5sWcLrjB1HO9ZH5nceWBg4cMKJvI/zT77h96fCy7uMkPNt867GP8O9KkWVWzxGBkpIdstigNWfT5g= -# name: "Current output" -# body: "![](https://img.shields.io/badge/dynamic/xml.svg?label=Contained%20sets&colorB=4ac41d&url=https%3A%2F%2Fraw.githubusercontent.com%2FCockatrice%2FMagic-Spoiler%2Ffiles%2Fspoiler.xml&query=%2F%2Flongname)
Most recent spoiler.xml (put date here)" -# file_glob: true -# file: out/spoiler.xml -# skip_cleanup: true -# overwrite: true -# draft: false -# prerelease: true -# on: -# repo: Cockatrice/Magic-Spoiler -# branch: master - -## Deployment of fully spoiled sets for archive reasons (on tags) -# - provider: releases -# api_key: -# secure: Bin220gU9Re176T/1bIaX/rhGB+uEaw13aoB2/ir0ePHQB0ihasEJcsgmlN8kz93KSN6vp4y2HwMLnz3t7Pn0amTV8QVL/AlOOzjbq8m/1kYTbXdPlYnMsosZPVFLHRan4LEGFsovRia6LO4p9fqC8BDgQl89W/88PlYAMWzao5jTyKKHp8o+sioYhKj9D+86lxLYspQ+6SN0HOCnF2MZ/vZtxbY32ituswAc/sJK1MtZ/PExoMe1nSI2iKCaatXyKA+FVCUNLHRAu4LgB1GfJCLpmlPbvjud8A6WAKNF6poNCvFck+Ox56tt4bw3ggR5W9kTEhvX74l6AEeC7Qz6bHjh1CEngrqFjyaHy25CcygWgagf0DUsvyGRS0RqEx4bz9psD09d+oWihdkJMfa5kRzXtVQD8sxDgsBqEz/DjsMIlf/L5ISSa7lAYiqq65ELpezBFOlvEZ9avOYLcZc7m5/5ZhtcA4HPSqzfn2nhkPpeggBKufMdyc8JIDkvs/JlFsNu46QVvugjbdGvtb4SlQK310py0TOA6nYt7WntDhX3SukKAeh6oHjZaL5aeoSBhnlQRgJfDBqI3+7anLatD30uEKCMp5sWcLrjB1HO9ZH5nceWBg4cMKJvI/zT77h96fCy7uMkPNt867GP8O9KkWVWzxGBkpIdstigNWfT5g= -# body: "Thanks to everyone who assisted with code or provided data corrections." -# file_glob: true -# file: out/*.xml -# skip_cleanup: true -# overwrite: true -# draft: true -# prerelease: false -# on: -# tags: true -# repo: Cockatrice/Magic-Spoiler -# branch: master -# condition: $TRAVIS_TAG =~ ^[0-9] # regex to skip automatically added "untagged" tags from continious deployment "Current output" - - -notifications: - email: false - webhooks: - urls: - - https://webhooks.gitter.im/e/691b9acffe1def5f9d6b - on_success: change # options: [always|never|change] default: always - on_failure: change # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always diff --git a/magic_spoiler/__main__.py b/magic_spoiler/__main__.py index 52698d2e..b8aef5ee 100644 --- a/magic_spoiler/__main__.py +++ b/magic_spoiler/__main__.py @@ -7,6 +7,7 @@ import hashlib import json import pathlib import shutil +import sys import time from typing import IO, Any, Dict, List, Tuple, Union @@ -366,10 +367,11 @@ def write_cards( card_xml_file.write("\n") -def write_spoilers_xml(trice_dicts: Dict[str, List[Dict[str, Any]]]) -> None: +def write_spoilers_xml(trice_dicts: Dict[str, List[Dict[str, Any]]]) -> bool: """ Write the spoiler.xml file :param trice_dicts: Dict of dict entries + :return: Written successfully """ output_file_name = "spoiler.xml" @@ -394,20 +396,22 @@ def write_spoilers_xml(trice_dicts: Dict[str, List[Dict[str, Any]]]) -> None: old_xml_location = str(OUTPUT_DIR.joinpath(output_file_name)) if compare_xml_content(card_xml_file.name, old_xml_location): print("No new data in spoiler.xml, skipping replacement") - return + return False # Move new version to old location print("Changes detected, replacing spoiler.xml with updated version") shutil.move(card_xml_file.name, old_xml_location) + return True -def write_spoilers_json(trice_dicts: Dict[str, List[Dict[str, Any]]]) -> None: +def write_spoilers_json(trice_dicts: Dict[str, List[Dict[str, Any]]]) -> bool: """ Dump the JSON into a spoiler file :param trice_dicts: All spoiled cards + :return: Written successfully """ if not trice_dicts: - return + return False output_file_path = OUTPUT_TMP_DIR.joinpath("spoiler.json") @@ -419,11 +423,12 @@ def write_spoilers_json(trice_dicts: Dict[str, List[Dict[str, Any]]]) -> None: old_xml_location = str(OUTPUT_DIR.joinpath("spoiler.json")) if compare_json_content(str(output_file_path), old_xml_location): print("No new data in spoiler.json, skipping replacement") - return + return False # Move new version to old location print("Changes detected, replacing spoiler.json with updated version") shutil.move(str(output_file_path), old_xml_location) + return True def compare_json_content(f1: str, f2: str) -> bool: @@ -473,14 +478,15 @@ def compare_xml_content(f1: str, f2: str) -> bool: return False -def write_set_xml(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> None: +def write_set_xml(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> bool: """ Write out a single magic set to XML format :param trice_dict: Cards to print :param set_obj: Set object + :return: Written successfully """ if not trice_dict: - return + return False OUTPUT_TMP_DIR.mkdir(exist_ok=True) card_xml_file = OUTPUT_TMP_DIR.joinpath("{}.xml".format(set_obj["code"])).open("w") @@ -495,7 +501,7 @@ def write_set_xml(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> old_xml_location = str(OUTPUT_DIR.joinpath("{}.xml".format(set_obj["code"]))) if compare_xml_content(card_xml_file.name, old_xml_location): print("No new data in {}.xml, skipping replacement".format(set_obj["code"])) - return + return False # Move new version to old location print( @@ -504,16 +510,18 @@ def write_set_xml(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> ) ) shutil.move(card_xml_file.name, old_xml_location) + return True -def write_set_json(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> None: +def write_set_json(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> bool: """ Dump the JSON into a spoiler file :param trice_dict: Cards :param set_obj: Set Information + :return: Written successfully """ if not trice_dict: - return + return False output_file_path = OUTPUT_TMP_DIR.joinpath("{}.json".format(set_obj["code"])) @@ -525,7 +533,7 @@ def write_set_json(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> old_xml_location = str(OUTPUT_DIR.joinpath("{}.json".format(set_obj["code"]))) if compare_json_content(str(output_file_path), old_xml_location): print("No new data in {}.json, skipping replacement".format(set_obj["code"])) - return + return False # Move new version to old location print( @@ -534,6 +542,7 @@ def write_set_json(trice_dict: List[Dict[str, Any]], set_obj: Dict[str, str]) -> ) ) shutil.move(str(output_file_path), old_xml_location) + return True def get_spoiler_sets() -> List[Dict[str, str]]: @@ -559,9 +568,10 @@ def get_spoiler_sets() -> List[Dict[str, str]]: return spoiler_sets -def delete_old_files() -> None: +def delete_old_files() -> bool: """ Delete files that are no longer necessary within the program + :return: Files were deleted """ valid_files = [x["code"].upper() for x in SPOILER_SETS.get()] + [ "spoiler", @@ -569,12 +579,14 @@ def delete_old_files() -> None: "README", ] - for file in OUTPUT_DIR.glob("*"): - if not file.is_file(): + deleted = False + for output_file in OUTPUT_DIR.glob("*"): + if not output_file.is_file(): continue - if file.stem not in valid_files: - file.unlink() + if output_file.stem not in valid_files: + output_file.unlink() + deleted = True if OUTPUT_TMP_DIR.is_dir(): shutil.rmtree(OUTPUT_TMP_DIR) @@ -584,6 +596,8 @@ def delete_old_files() -> None: else: OUTPUT_DIR.joinpath("SpoilerSeasonEnabled").open("w").write(" ") + return deleted + def main() -> None: """ @@ -594,6 +608,7 @@ def main() -> None: SPOILER_SETS.set(get_spoiler_sets()) spoiler_xml = {} + changed = False for set_info in SPOILER_SETS.get(): print("Handling {}".format(set_info["code"])) @@ -601,19 +616,23 @@ def main() -> None: trice_dict = scryfall2mtgjson(cards) # Write SET.xml - write_set_xml(trice_dict, set_info) - write_set_json(trice_dict, set_info) + changed |= write_set_xml(trice_dict, set_info) + changed |= write_set_json(trice_dict, set_info) # Save for spoiler.xml spoiler_xml[set_info["code"]] = trice_dict if spoiler_xml: # Write out the spoiler.xml file - write_spoilers_xml(spoiler_xml) - write_spoilers_json(spoiler_xml) + changed |= write_spoilers_xml(spoiler_xml) + changed |= write_spoilers_json(spoiler_xml) # Cleanup outdated stuff that's not necessary - delete_old_files() + changed |= delete_old_files() + + # Set nonzero exit code if files haven't changed + if not changed: + sys.exit(1) if __name__ == "__main__":