From 45ac553e21a1ff507b5b4291b7bd6499346af3e7 Mon Sep 17 00:00:00 2001 From: Guredora <66153480+guredora403@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:57:23 +0900 Subject: [PATCH] =?UTF-8?q?Github=20actions=E3=81=A7=E3=81=AE=E8=87=AA?= =?UTF-8?q?=E5=8B=95=E3=83=93=E3=83=AB=E3=83=89=E3=81=A8=E3=83=AA=E3=83=AA?= =?UTF-8?q?=E3=83=BC=E3=82=B9=20(#3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix build script for Github actions * Add snapshot build workflow on Github actions * fix directory name * fix deleting release * fix version of github-script * fix typo * fix tag re-creating * fix typo * fix error * fix workflow * test for ci * delete error handling * add deploy job * スクリプトの変更 * add error handling * fix typo * Enabling LFS * Set false to lfs for test * add slack alert test * alert test * Split build and test jobs into the reusable workflow * add job section * fix typo * set snapshot release name * add release workflow * add pullrequest workflow * chaching pip dependency * add register to actlab site * set lfs true * fix secret name SLACK_WORKFLOW_WEBHOOK_URL to SLACK_ALERT_WEBHOOK_URL * Add support for Japanese Standard Time in makeSnapshotVersionNumber() * test register to beta server * fix import error * fix import error * install WX for register actlab site * fix urllib error * built version output * fix typo * Fixed missing parentheses * add imports * fixed github output path * add quotation * delete test code * turn off LFS function of checkout * Remove checkout step in release and snapshot deploy jobs * Remove Appveyor configuration files --- .github/workflows/pullRequest.yml | 10 ++++ .github/workflows/release.yml | 49 ++++++++++++++++++ .github/workflows/snapshot.yml | 83 ++++++++++++++++++++++++++++++ .github/workflows/testAndBuild.yml | 67 ++++++++++++++++++++++++ appveyor-release.yml | 53 ------------------- appveyor.yml | 71 ------------------------- tools/build.py | 36 ++++++------- 7 files changed, 224 insertions(+), 145 deletions(-) create mode 100644 .github/workflows/pullRequest.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/snapshot.yml create mode 100644 .github/workflows/testAndBuild.yml delete mode 100644 appveyor-release.yml delete mode 100644 appveyor.yml diff --git a/.github/workflows/pullRequest.yml b/.github/workflows/pullRequest.yml new file mode 100644 index 0000000..9284177 --- /dev/null +++ b/.github/workflows/pullRequest.yml @@ -0,0 +1,10 @@ +name: check for pull request into master + +on: + pull_request: + branches: + - master + +jobs: + build: + uses: ./.github/workflows/testAndBuild.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..54272cf --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,49 @@ +name: Build and release for official + +on: + push: + tags: + - "*.*.*" + +jobs: + build: + uses: ./.github/workflows/testAndBuild.yml + with: + official_release: true + + deploy: + needs: build + runs-on: windows-latest + + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ github.event.repository.name }} + path: ./ + + - name: Deploy to GitHub + uses: softprops/action-gh-release@v1 + with: + body: ${{ github.event.repository.name }} official release + draft: true + files: | + ./${{ github.event.repository.name }}-*.zip + ./${{ github.event.repository.name }}-*.json + + error_notify: + runs-on: ubuntu-latest + needs: deploy + if: ${{ failure() }} + steps: + - name: Send GitHub Action trigger data to Slack workflow + uses: slackapi/slack-github-action@v1 + with: + payload: | + { + "text": "Github actions build failed! <${{ github.server_url }}/${{ github.repository }}|${{ github.event.repository.name }}>のofficial releaseビルドが失敗しました。\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|対象のrun>お確認し、対応着手時・完了後は、本チャンネルにて経緯を報告ください。" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_ALERT_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 0000000..6fe5d79 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,83 @@ +name: Build and release for snapshot + +on: + push: + branches: + - master + +jobs: + build: + uses: ./.github/workflows/testAndBuild.yml + + deploy: + needs: build + runs-on: windows-latest + + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ github.event.repository.name }} + path: ./ + + - name: Re-create the tag + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo + const tagName = repo + "-latestcommit" + try { + // Fetch the release by its tag + const { data: release } = await github.rest.repos.getReleaseByTag({ owner, repo, tag: tagName }) + // Delete the release if exists + await github.rest.repos.deleteRelease({ owner, repo, release_id: release.id }) + console.log("deleted release"); + } catch(err) { + if(err.status !== 404){ + throw err; + } + console.log('No release found for deletion'); + } + try { + await github.rest.git.deleteRef({owner, repo, ref: "tags/" + tagName}) + console.log("deleted tag"); + } catch(err) { + console.log('Failed to delete tag'+err.message); + } + try { + await github.rest.git.createRef({owner, repo, ref: "refs/tags/" + tagName, sha: context.sha}) + console.log("created tag"); + } catch(err) { + console.log('Failed to create tag'+err.message); + } + + - name: Deploy to GitHub + uses: softprops/action-gh-release@v1 + with: + name: Snapshot + tag_name: ${{ github.event.repository.name }}-latestcommit + body: Automatic build from master branch + files: | + ./${{ github.event.repository.name }}-*.zip + ./${{ github.event.repository.name }}-*.json + + - name: register snapshot to actlab site + run: | + curl "https://actlab.org/api/addAlphaVersion?repo_name=${{ github.repository }}&commit_hash=${{ github.sha }}&version=${{ needs.build.outputs.build_version }}&password=${{ secrets.SCRIPT_PASSWORD }}" + + error_notify: + runs-on: ubuntu-latest + needs: deploy + if: ${{ failure() }} + steps: + - name: Send GitHub Action trigger data to Slack workflow + uses: slackapi/slack-github-action@v1 + with: + payload: | + { + "text": "Github actions build failed! <${{ github.server_url }}/${{ github.repository }}|${{ github.event.repository.name }}>のビルドが失敗しました。\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|対象のrun>お確認し、対応着手時・完了後は、本チャンネルにて経緯を報告ください。" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_ALERT_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + diff --git a/.github/workflows/testAndBuild.yml b/.github/workflows/testAndBuild.yml new file mode 100644 index 0000000..e56a205 --- /dev/null +++ b/.github/workflows/testAndBuild.yml @@ -0,0 +1,67 @@ +name: Test and build + +on: + workflow_call: + inputs: + official_release: + description: Whether this is an official release + default: false + type: boolean + outputs: + build_version: + description: Version of the built package + value: ${{ jobs.build.outputs.build_version }} + +jobs: + build: + runs-on: windows-latest + outputs: + build_version: ${{ steps.output_version.outputs.version }} + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + architecture: x86 + python-version: 3.8 + cache: pip + + - name: Install requirements + run: | + python -m pip install -r requirements.txt + + - name: Test + run: | + python -m unittest discover test + + - name: Set tag name if This is an official release + run: echo "TAG_NAME=$($env:GITHUB_REF.Replace('refs/tags/', ''))" >> $env:GITHUB_ENV + if: ${{ inputs.official_release }} + + - name: Build + run: | + python tools\build.py + env: + COMMIT_TIMESTAMP: ${{ github.event.head_commit.timestamp}} + + - name: output version + id: output_version + shell: python + run: | + import os, sys + sys.path.append(os.getcwd()) + import constants + with open(os.environ["GITHUB_OUTPUT"], mode = "a") as f: + f.write("version="+constants.APP_VERSION) + + - name: Archive production artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ github.event.repository.name }} + path: | + ./${{ github.event.repository.name }}-*.zip + ./${{ github.event.repository.name }}-*.json + diff --git a/appveyor-release.yml b/appveyor-release.yml deleted file mode 100644 index 4d0b862..0000000 --- a/appveyor-release.yml +++ /dev/null @@ -1,53 +0,0 @@ -version: development.{build}-{branch} -branches: - only: - - release - -skip_branch_with_pr: true - -environment: - matrix: - # For Python versions available on Appveyor, see - # http://www.appveyor.com/docs/installed-software#python - # The list here is complete (excluding Python 2.6, which - # isn't covered by this document) at the time of writing. - - - PYTHON: "C:\\Python38" - -install: - # We need wheel installed to build wheels - - "%PYTHON%\\python.exe -m pip install -r requirements.txt" - -build: off - -test_script: - # Put your test command here. - # If you don't need to build C extensions on 64-bit Python 3.3 or 3.4, - # you can remove "build.cmd" from the front of the command, as it's - # only needed to support those cases. - # Note that you must use the environment variable %PYTHON% to refer to - # the interpreter you're using - Appveyor does not do anything special - # to put the Python evrsion you want to use on PATH. - - "%PYTHON%\\python.exe -m unittest discover test" - -after_test: - # This step builds your wheels. - # Again, you only need build.cmd if you're building C extensions for - # 64-bit Python 3.3/3.4. And you need to use %PYTHON% to get the correct - # interpreter - - "%PYTHON%\\python.exe tools\\build.py --appveyor" - -artifacts: - - path: PVP-*.zip - - path: PVP-*.json - -deploy: - - provider: GitHub - description: "PVP official release" - auth_token: - secure: iNSx8v6c+0TP9IyckinrvNWuX+hc7SKruOqRDl9GxdX59sZ2yqB8+UDAtqdPzKIg - artifact: /(PVP-.*\.zip)|(PVP-.*\.json)/ - draft: true - prerelease: false - on: - APPVEYOR_REPO_TAG: true diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 09cac3d..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,71 +0,0 @@ -version: development.{build}-{branch} -branches: - only: - - master - -skip_branch_with_pr: true -skip_tags: true - -environment: - githubToken: - secure: iNSx8v6c+0TP9IyckinrvNWuX+hc7SKruOqRDl9GxdX59sZ2yqB8+UDAtqdPzKIg - SCRIPT_PASSWORD: - secure: 9RvVUKVQ8MsoG5LOZ86VyFQF19JXXS33tDzomLH/jZM= - matrix: - - # For Python versions available on Appveyor, see - # http://www.appveyor.com/docs/installed-software#python - # The list here is complete (excluding Python 2.6, which - # isn't covered by this document) at the time of writing. - - - PYTHON: "C:\\Python38" - -install: - # We need wheel installed to build wheels - - "%PYTHON%\\python.exe -m pip install -r requirements.txt" - -build: off - -test_script: - # Put your test command here. - # If you don't need to build C extensions on 64-bit Python 3.3 or 3.4, - # you can remove "build.cmd" from the front of the command, as it's - # only needed to support those cases. - # Note that you must use the environment variable %PYTHON% to refer to - # the interpreter you're using - Appveyor does not do anything special - # to put the Python evrsion you want to use on PATH. - - "%PYTHON%\\python.exe -m unittest discover test" - -after_test: - # This step builds your wheels. - # Again, you only need build.cmd if you're building C extensions for - # 64-bit Python 3.3/3.4. And you need to use %PYTHON% to get the correct - # interpreter - - "%PYTHON%\\python.exe tools\\build.py --appveyor" - - cmd: if defined APPVEYOR_PULL_REQUEST_NUMBER appveyor exit 0 - - cmd: curl "https://actlab.org/git-release.php?repo_name=%APPVEYOR_REPO_NAME%&tag_name=PVP-latestcommit&password=%SCRIPT_PASSWORD%" - - cmd: git tag -d PVP-latestcommit - - cmd: git push -d https://actlab-auto:%githubToken%@github.com/actlaboratory/PVP.git PVP-latestcommit - - cmd: git tag PVP-latestcommit - - cmd: git push https://actlab-auto:%githubToken%@github.com/actlaboratory/PVP.git PVP-latestcommit - -artifacts: - - path: PVP-*.zip - - path: PVP-*.json - -deploy: - - provider: GitHub - release: PVP-latestcommit - skip_tags: true - Force update: true - description: 'automatic build from master branch' - auth_token: - secure: iNSx8v6c+0TP9IyckinrvNWuX+hc7SKruOqRDl9GxdX59sZ2yqB8+UDAtqdPzKIg - artifact: /(PVP-.*\.zip)|(PVP-.*\.json)/ # upload all NuGet packages to release assets - draft: false - prerelease: false - on: - branch: master # release from master branch only - -after_deploy: - - cmd: echo import constants;print("https://actlab.org/api/addAlphaVersion?repo_name=%APPVEYOR_REPO_NAME%&commit_hash=%APPVEYOR_REPO_COMMIT%&version="+constants.APP_VERSION+"&password=%SCRIPT_PASSWORD%",end="") | %PYTHON%\\python.exe | xargs -n1 curl diff --git a/tools/build.py b/tools/build.py index 828c5a5..873fd1f 100644 --- a/tools/build.py +++ b/tools/build.py @@ -30,23 +30,20 @@ class build: def __init__(self): - # appVeyorかどうかを判別し、処理をスタート - appveyor = self.setAppVeyor() - print("Starting build for %s(appveyor mode=%s)" % (constants.APP_NAME, appveyor)) + # Github actionsなどの自動実行かどうかを判別し、処理をスタート + automated = self.setAutomated() + print("Starting build for %s(automated mode=%s)" % (constants.APP_NAME, automated)) # パッケージのパスとファイル名を決定 package_path = os.path.join("dist", os.path.splitext(os.path.basename(constants.STARTUP_FILE))[0]) - if 'APPVEYOR_REPO_TAG_NAME' in os.environ: - build_filename = os.environ['APPVEYOR_REPO_TAG_NAME'] - else: - build_filename = 'snapshot' + build_filename = os.environ.get('TAG_NAME', 'snapshot') print("Will be built as %s" % build_filename) # pyinstallerのパスを決定 - if not appveyor: - pyinstaller_path = "pyinstaller.exe" + if automated: + pyinstaller_path = "%pythonLocation%\\Scripts\\pyinstaller.exe" else: - pyinstaller_path = "%PYTHON%\\Scripts\\pyinstaller.exe" + pyinstaller_path = "pyinstaller.exe" print("pyinstaller_path=%s" % pyinstaller_path) hooks_path = os.path.join(PyInstaller.__path__[0], "hooks/") print("hooks_path is %s" % (hooks_path)) @@ -59,8 +56,8 @@ def __init__(self): # 前のビルドをクリーンアップ self.clean(package_path) - # appveyorでのスナップショットの場合はバージョン番号を一時的に書き換え - if build_filename == "snapshot" and appveyor: + # 自動実行でのスナップショットの場合はバージョン番号を一時的に書き換え + if build_filename == "snapshot" and automated: self.makeSnapshotVersionNumber() # ビルド @@ -69,7 +66,7 @@ def __init__(self): archive_name = "%s-%s.zip" % (constants.APP_NAME, build_filename) # スナップショットでなければ - if build_filename == "snapshot" and not appveyor: + if build_filename == "snapshot" and not automated: print("Skipping batch archiving because this is a local snapshot.") else: patch_name = self.makePatch(build_filename, archive_name) @@ -83,10 +80,8 @@ def runcmd(self,cmd): proc.communicate() return proc.poll() - def setAppVeyor(self): - if len(sys.argv)>=2 and sys.argv[1]=="--appveyor": - return True - return False + def setAutomated(self): + return os.environ.get("GITHUB_ACTIONS", "false") == "true" def clean(self,package_path): if os.path.isdir(package_path): @@ -97,9 +92,8 @@ def clean(self,package_path): def makeSnapshotVersionNumber(self): #日本標準時オブジェクト JST = datetime.timezone(datetime.timedelta(hours=+9)) - #Pythonは世界標準時のZに対応していないので文字列処理で乗り切り、それを日本標準時に変換 - dt = datetime.datetime.fromisoformat(os.environ["APPVEYOR_REPO_COMMIT_TIMESTAMP"][0:19]+"+00:00").astimezone(JST) - major = str(dt.year)[2:4]+str(dt.month).zfill(2) + dt = datetime.datetime.fromisoformat(os.environ["COMMIT_TIMESTAMP"]).astimezone(JST) + major = f"{dt.year % 100:02d}{dt.month:02d}" minor = str(dt.day) patch = str(int(math.floor((dt.hour*3600+dt.minute*60+dt.second)/86400*1000))) constants.APP_VERSION = major+"."+minor+"."+patch @@ -178,7 +172,7 @@ def addUpdater(self, archive_name): os.remove("updater.zip") def makePackageInfo(self, archive_name, patch_name, build_filename): - print("computing hash...") + print("Calculating hash...") with open(archive_name, mode = "rb") as f: package_hash = hashlib.sha1(f.read()).hexdigest() if constants.BASE_PACKAGE_URL is not None: