diff --git a/.github/workflows/build.yml b/.github/workflows/build-installer.yml similarity index 79% rename from .github/workflows/build.yml rename to .github/workflows/build-installer.yml index 3a527b1b..a6f0f66e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build-installer.yml @@ -1,10 +1,11 @@ name: build installer on: - push: - branches: [ master ] - pull_request: - branches: [ master ] +# push: +# branches: [ master ] +# pull_request: +# branches: [ master ] + workflow_dispatch: jobs: build-installer: diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml new file mode 100644 index 00000000..b7217a8d --- /dev/null +++ b/.github/workflows/deployment.yml @@ -0,0 +1,170 @@ +name: update-deploy + +on: + # Run on push to master + push: + branches: + - master + + # Run this manually + workflow_dispatch: + + workflow_run: + # Run this after the release workflow has completed + workflows: [ release ] + types: + - completed +jobs: + # This job uses a Docker Ubuntu container to download necessary files/tools from the server to create the update. + # An Ubuntu Docker container is necessary, because we have more control over what Ubuntu programs are available to us, + # because we can install them into a Github workflow container. + download-tools: + # This job requires an Ubuntu platform so that it can create the Ubuntu Docker container. + runs-on: ubuntu-latest + environment: cncnet + + steps: + # Checkout the repo + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 # required for gitversion + + # Run Gitversion - https://gitversion.net/docs/ + # This runs gitversion in a docker container and writes the output json to a local file. + # This output file will be available in the uploaded artifact later in the workflow. + - name: Run Gitversion Docker + run: docker run --rm -v "$(pwd):/repo" gittools/gitversion:latest-debian.10 /repo >gitversion.json + + # Get access to the properties from the gitversion output file + - name: Get gitversion.json properties + id: gitversion + uses: zoexx/github-action-json-file-properties@release + with: + file_path: "gitversion.json" + + # Update versionconfig.ini with gitversion version info + - name: Update versionconfig.ini + # replace the second line in the file with the proper version number (X.Y.Z-dev.N) + run: sed -i "2 s/.*/${{steps.gitversion.outputs.SemVer}}/" versionconfig.ini + + # We need to download necessary "tools" for the update (including VersionWriter.exe). Github Workflow linux containers do + # not the necessary programs installed by default and we do not have the ability to install it. + # So, we use our own Docker container to do so. + + # Build the container from our Dockerfile + - name: Build docker container + run: docker build -t download-tools ${{ github.workspace }}/updater-scripts/download-tools + + # Run the newly built container + - name: Run docker container + env: + # These are secret variables that should be stored in Github for the repository. + SSH_KEY: ${{ secrets.SSH_KEY }} + SSH_HOST: ${{ secrets.SSH_HOST }} + SSH_PASS: ${{ secrets.SSH_PASS }} + SSH_USER: ${{ secrets.SSH_USER }} + SSH_PATH_TOOLS: ${{ secrets.SSH_PATH_TOOLS }} + SSH_PORT: ${{ secrets.SSH_PORT }} + run: docker run -v ${{ github.workspace }}:/download-tools -e SSH_KEY -e SSH_HOST -e SSH_PASS -e SSH_USER -e SSH_PATH_TOOLS -e SSH_PORT -i download-tools + + # Archive this repo, excluding unnecessary files for the update + - name: Zip dependencies + run: zip -r archive.zip . -x *.git\* *.github\* *InnoSetup\* *.gitignore *.gitattributes + + # Upload the archive artifact for the next job + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: artifact + path: archive.zip + + # We have the necessary tools and the proper version has been written to our versionconfig.ini file. + # Now, we need to actually run VersionWriter.exe. + + version-writer: + # This jub runs runs on a Windows platform, because we need to run the VersionWriter executable. + runs-on: windows-latest + environment: cncnet + # Make sure we wait for the "download-tools" job to complete successfully + needs: download-tools + + steps: + # Download the previous artifact archive + - name: Get artifact + uses: actions/download-artifact@v2 + with: + name: artifact + + # Extract the archive + - name: Extract archive + run: 7z x archive.zip + + # Run the VersionWriter + - name: Run VersionWriter.exe + run: ./VersionWriter.exe /S + + # Remove files we do not want in the new archive + - name: Clean up files + run: rm archive.zip && rm VersionWriter.exe && rm -r VersionWriter-CopiedFiles + + # Create new archive + - name: Create new versioned archive + run: 7z a -r archive.zip . + + # Upload the versioned archive artifact for next job + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: artifact + path: archive.zip + + # We now have a zip file containing the exact files necessary for the next update. We need to + # upload these files to the server in the proper version folder. + + # This job creates the appropriate version folder on the server and uploads our updated files to it. + upload-version: + runs-on: ubuntu-latest + environment: cncnet + needs: version-writer + + steps: + # Download the previous artifact archive + - name: Get artifact + uses: actions/download-artifact@v2 + with: + name: artifact + + # Extract the archive + - name: Extract archive + run: 7z x archive.zip + + # Get access to the properties from the gitversion output file + - name: Get gitversion.json properties + id: gitversion + uses: zoexx/github-action-json-file-properties@release + with: + file_path: "gitversion.json" + + # Create deploy archive + - name: Create deploy archive + run: tar --exclude=*updater-scripts\* --exclude=archive.zip -czvf archive.tar.gz * + + # Build the container from our Dockerfile + - name: Build docker container + run: docker build -t upload-version ${{ github.workspace }}/updater-scripts/upload-version + + # Run the newly built container + - name: Run docker container + env: + # These are secret variables that should be stored in Github for the repository. + SSH_KEY: ${{ secrets.SSH_KEY }} + SSH_HOST: ${{ secrets.SSH_HOST }} + SSH_PASS: ${{ secrets.SSH_PASS }} + SSH_USER: ${{ secrets.SSH_USER }} + SSH_PATH_UPDATES: ${{ secrets.SSH_PATH_UPDATES }} + SSH_PORT: ${{ secrets.SSH_PORT }} + VERSION: ${{ steps.gitversion.outputs.MajorMinorPatch }}${{ steps.gitversion.outputs.PreReleaseLabelWithDash }} + run: docker run -v ${{ github.workspace }}:/upload-version -e SSH_KEY -e SSH_HOST -e SSH_PASS -e SSH_USER -e SSH_PATH_UPDATES -e SSH_PORT -e VERSION -i upload-version + + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..d73e136b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,14 @@ +name: release + +on: + release: + types: [ published ] + +jobs: + noop: + # restrict this to only run for tags that start with 'yr-' + if: startsWith(${{ github.ref }}, 'refs/tags/yr-') + runs-on: ubuntu-latest + steps: + - name: noop + run: echo Release created for tag ${{ github.ref }} diff --git a/.gitignore b/.gitignore index 25e324d4..95086ba6 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,4 @@ ra2md.mix stats.dmp wdt.mix /InnoSetup/output +/gitversion.json diff --git a/DEPLOYMENTS.md b/DEPLOYMENTS.md new file mode 100644 index 00000000..befcb37c --- /dev/null +++ b/DEPLOYMENTS.md @@ -0,0 +1,40 @@ +# CnCNet Yuri's Revenge Client Package Deployments + +This describes the workflow for release/deployments. + +## Versioning + +Deployments are currently set up for [Continuous Deployment](https://gitversion.net/docs/reference/modes/continuous-deployment). Versioning is auto incremented. There are two triggers for deployments and versioning: + +1. Publishing a release: When a release is created, the corresponding tag name should be created in the format **yr-X.Y** or **yr-X.Y.Z**, where **X** is major, **Y** is minor, and **Z** is an optional patch. When a tag is created in this format, a deployment will occur for that exact version. Examples: + 1. If the tag **yr-8.7** is created, the next deployed version in this case will be **8.7.0**. + 2. If the tag **yr-8.7.1** is created, the next deployed version in this case will be **8.7.1**. + +2. Merging into master: When this happens, an auto incremented dev version of the client will be created and deployed. This auto incremented version will be the last **tag** version +1 patch. Examples: + + 1. If the latest tag is **yr-8.6**, the next deployed version will be **8.6.1-dev**. + 2. If the latest tag is **yr-8.6.1**, the next deployed version will be **8.6.2-dev**. + +## Workflow + +This seciton describes the proper workflow for publishing new versions of the client. Below is an example of a "current state" scenario. + +Current state: The client is on version **8.6** and a git tag of **yr-8.6** exists. + +1. A PR of new code is created and merged OR code is pushed directly to master. +2. The **deployment** Github Action is triggered and deploys the version **8.6.1-dev** to the server. The **version** file generated by VersionWriter.exe will have the version of **8.6.1-dev.1**. +3. **yrdev** on the server is linked to **8.6.1-dev** deployment (**manual process**). This version is now live for dev testers. +4. Another PR of new code is created and merged OR code is pushed directly to master. +5. The **deployment** Github Action is triggered and deploys an updated version of **8.6.1-dev** to the server. The **version** file generated by VersionWriter.exe will have the version of **8.6.1-dev.2**. This should trigger an update notification for anyone testing dev versions. +6. The version **8.6.1-dev** has been determined to be stable and is tagged in Github as **yr-8.7** (**manual process**). +7. The **release** Github Action is triggered. This then triggers the **deployment** Github Action which deploys the version **8.7.0** to the server. +8. **yrdev** on the server is linked to **8.7.0** (**manual process**) + * This is optionally done for "smoke testing" purposes. However, if the tag was created from the latest commit in the **master** branch, which should have been the latest version deployed to **8.6.1-dev**, the versions **8.6.1-dev** and **8.7.0** are essentially the same. +9. **yr** on the server is linked to **8.7.0**. This version is now live for all. + +## Security and Approvals + +For security reasons, the **master** branch has protection rules in place to prevent unauthorized pushes/merges to master and thus unauthorized deployments. +1. Pushes directly to master are disabled for non admins. Changes to master must be made through a PR. +2. PRs for non admins require a minimum of 1 approval. +3. Approvals on PRs that are "updated" by new commits are immediately dismissed. These PRs must be re-approved. diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 00000000..1e75c258 --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,3 @@ +tag-prefix: 'yr-' +continuous-delivery-fallback-tag: dev +mode: ContinuousDeployment diff --git a/README.md b/README.md index e7c38008..f40cc9bc 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,17 @@ # CnCNet Yuri's Revenge Client Package -The official CnCNet [Yuri's Revenge](https://cncnet.org/yuris-revenge) package for online. +The official CnCNet [Yuri's Revenge](https://cncnet.org/yuris-revenge) package for online. This package is an add-on to the [XNA CnCNet Client](https://github.com/CnCNet/xna-cncnet-client) by [Rampastring](https://github.com/Rampastring) +### Contributing - -### Contributing * [dkeetonx](https://github.com/dkeetonx) * [GrantBartlett](https://github.com/GrantBartlett) * [Martin](https://forums.cncnet.org/profile/32538-ravage/) * [Kerbiter](https://github.com/Metadorius) -* [Burg](https://github.com/alexp8) \ No newline at end of file +* [Burg](https://github.com/alexp8) +* [devo1929](htttps://github.com/devo1929) + +### Deployments + +[Documentation](DEPLOYMENTS.md) diff --git a/updater-scripts/download-tools.sh b/updater-scripts/download-tools.sh new file mode 100644 index 00000000..a8b28724 --- /dev/null +++ b/updater-scripts/download-tools.sh @@ -0,0 +1,13 @@ +#!/bin/sh +SSH_KEY_FILE=$1 +SSH_USER=$2 +SSH_PASS=$3 +SSH_HOST=$4 +SSH_PATH_TOOLS=$5 +SSH_PORT=$6 + +chmod 400 $SSH_KEY_FILE + +echo downloading tools +sshpass -p $SSH_PASS -P passphrase scp -o StrictHostKeyChecking=no -i $SSH_KEY_FILE -P $SSH_PORT $SSH_USER@$SSH_HOST:$SSH_PATH_TOOLS/gamemd-spawn.exe ./tools +sshpass -p $SSH_PASS -P passphrase scp -o StrictHostKeyChecking=no -i $SSH_KEY_FILE -P $SSH_PORT $SSH_USER@$SSH_HOST:$SSH_PATH_TOOLS/VersionWriter.exe ./tools diff --git a/updater-scripts/download-tools/Dockerfile b/updater-scripts/download-tools/Dockerfile new file mode 100644 index 00000000..0f60c58d --- /dev/null +++ b/updater-scripts/download-tools/Dockerfile @@ -0,0 +1,8 @@ +FROM ubuntu:latest + +RUN apt-get update && apt-get install -y sshpass + +COPY entrypoint.sh / +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] + diff --git a/updater-scripts/download-tools/entrypoint.sh b/updater-scripts/download-tools/entrypoint.sh new file mode 100644 index 00000000..7a213ea3 --- /dev/null +++ b/updater-scripts/download-tools/entrypoint.sh @@ -0,0 +1,22 @@ +#!/bin/bash +#uncomment this ONLY when running locally, for debugging output purposes +#set -x + +# create our key file to pass to scp +cd download-tools +echo -e ${SSH_KEY}>__tmp_key_file +chmod 400 __tmp_key_file + +# download necessary tools for update +echo uploading version +sshpass -p ${SSH_PASS} -P passphrase scp -o StrictHostKeyChecking=no -i __tmp_key_file -P ${SSH_PORT} ${SSH_USER}@${SSH_HOST}:${SSH_PATH_TOOLS}/gamemd-spawn.exe . +sshpass -p ${SSH_PASS} -P passphrase scp -o StrictHostKeyChecking=no -i __tmp_key_file -P ${SSH_PORT} ${SSH_USER}@${SSH_HOST}:${SSH_PATH_TOOLS}/VersionWriter.exe . + +# clean up temporary key file +rm __tmp_key_file + +# uncomment this to debug the directory contents during github action +dir + +# uncomment this when running locally to keep the container alive for debugging purposes +#tail -f /dev/null diff --git a/updater-scripts/upload-version/Dockerfile b/updater-scripts/upload-version/Dockerfile new file mode 100644 index 00000000..0f60c58d --- /dev/null +++ b/updater-scripts/upload-version/Dockerfile @@ -0,0 +1,8 @@ +FROM ubuntu:latest + +RUN apt-get update && apt-get install -y sshpass + +COPY entrypoint.sh / +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] + diff --git a/updater-scripts/upload-version/entrypoint.sh b/updater-scripts/upload-version/entrypoint.sh new file mode 100644 index 00000000..4ea6f151 --- /dev/null +++ b/updater-scripts/upload-version/entrypoint.sh @@ -0,0 +1,33 @@ +#!/bin/bash +#uncomment this ONLY when running locally, for debugging output purposes +#set -x + +# create our key file to pass to scp +cd upload-version +echo -e ${SSH_KEY}>__tmp_key_file +chmod 400 __tmp_key_file + +# create necessary version folder for update +echo creating version folder +sshpass -p ${SSH_PASS} -P passphrase ssh -o StrictHostKeyChecking=no -i __tmp_key_file -p ${SSH_PORT} ${SSH_USER}@${SSH_HOST} mkdir ${SSH_PATH_UPDATES}/${VERSION} + +# upload deploy archive +sshpass -p ${SSH_PASS} -P passphrase scp -o StrictHostKeyChecking=no -i __tmp_key_file -P ${SSH_PORT} archive.tar.gz ${SSH_USER}@${SSH_HOST}:${SSH_PATH_UPDATES}/${VERSION}/ + +# extract the deploy archive +sshpass -p ${SSH_PASS} -P passphrase ssh -o StrictHostKeyChecking=no -i __tmp_key_file -p ${SSH_PORT} ${SSH_USER}@${SSH_HOST} tar -xzvf ${SSH_PATH_UPDATES}/${VERSION}/archive.tar.gz -C ${SSH_PATH_UPDATES}/${VERSION} + +# delete the deploy archive from server +sshpass -p ${SSH_PASS} -P passphrase ssh -o StrictHostKeyChecking=no -i __tmp_key_file -p ${SSH_PORT} ${SSH_USER}@${SSH_HOST} rm ${SSH_PATH_UPDATES}/${VERSION}/archive.tar.gz + +# update permissions on all update files for update download purposes +sshpass -p ${SSH_PASS} -P passphrase ssh -o StrictHostKeyChecking=no -i __tmp_key_file -p ${SSH_PORT} ${SSH_USER}@${SSH_HOST} chmod 777 --recursive ${SSH_PATH_UPDATES}/${VERSION}/* + +# clean up temporary key file +rm __tmp_key_file + +# uncomment this to debug the directory contents during github action +dir + +# uncomment this when running locally to keep the container alive for debugging purposes +#tail -f /dev/null