# # # @type github workflow # @author Aetherinox # @url https://github.com/Aetherinox # @usage deploys docker container to github and send message to discord # upload this workflow to both the `main` branch of the tvapp2 repository # @secrets secrets.ADMINSERV_GPG_KEY_ASC gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK # secrets.ADMINSERV_GPG_PASSPHRASE gpg private key passphrase # secrets.ORG_BINARYNINJA_TOKEN_CL github personal access token (classic) with package:write permission # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES Discord webhook to report releases from github to discord # # name: "📦 Deploy › Docker › Github" run-name: "📦 Deploy › Docker › Github" # # # Triggers # # on: # # # Trigger › Workflow Dispatch # # If any values are not provided, will use fallback env variable # # workflow_dispatch: inputs: # # # Image Name # # used in github image path # ghcr.io/${{ env.IMAGE_GHCR_AUTHOR }}/${{ env.IMAGE_NAME }} # # IMAGE_NAME: description: '📦 Image Name' required: true default: 'tvapp2' type: string # # # Image Version # # used to create new release tag, and add version to docker image name # # IMAGE_VERSION: description: '🏷️ Image Version' required: true default: '1.0.0' type: string # # # Image Author # # used in github image path # ghcr.io/${{ env.IMAGE_GHCR_AUTHOR }}/${{ env.IMAGE_NAME }} # # IMAGE_GHCR_AUTHOR: description: '🪪 Image Author' required: true default: 'TheBinaryNinja' type: string # # # Image ghcr username # # this is the user to sign into ghcr as. # # IMAGE_GHCR_USERNAME: description: '🪪 ghcr.io Username' required: true default: 'TheBinaryNinja' type: string # # # true no changes to the repo will be made # false workflow will behave normally, and push any changes detected to the files # # DRY_RUN: description: '🐛 Dry Run (Debug)' required: true default: false type: boolean # # # true released version will be marked as a development build and will have the v1.x.x-development tag instead of -latest # false release version will be marked with -latest docker tag # # DEV_RELEASE: description: '🧪 Development Release' required: true default: false type: boolean # # # Trigger › Push # # push: tags: - '*' # # # Environment Vars # # env: IMAGE_NAME: ${{ github.event.inputs.IMAGE_NAME || 'tvapp2' }} IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }} IMAGE_GHCR_AUTHOR: ${{ github.event.inputs.IMAGE_GHCR_AUTHOR || 'BinaryNinja' }} IMAGE_GHCR_USERNAME: ${{ github.event.inputs.IMAGE_GHCR_USERNAME || 'BinaryNinja' }} BOT_NAME_1: EuropaServ BOT_NAME_DEPENDABOT: dependabot[bot] # # # Jobs # # The way pushed docker containers on Github work, the most recent image built goes at the top. # We will use the order below which builds the :latest image last so that it appears at the very # top of the packages page. # # jobs: # # # Job › Create Tag # # job-docker-release-tags-create: name: >- 📦 Release › Create Tag # runs-on: ubuntu-latest runs-on: apollo-x64 timeout-minutes: 4 permissions: contents: write packages: write attestations: write id-token: write steps: # # # Release › Tags › Start # # - name: '🏳️ Start' id: task_release_tags_start run: | echo "Creating Tag" # # # Release › Tags › Checkout # # - name: '✅ Checkout' id: task_release_tags_checkout uses: actions/checkout@v4 with: fetch-depth: 0 # # # Release › Tags › Fix Permissions # # - name: '#️⃣ Manage Permissions' id: task_release_tags_permissions run: | find ./ -name 'run' -exec chmod 755 {} \; WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print) if [ -n "${WRONG_PERM}" ]; then echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️" for i in ${WRONG_PERM}; do echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!" done exit 1 else echo "✅✅✅ Executable permissions are OK ✅✅✅" fi # # # Release › Tags › Create Tag # # only called in dispatch mode # # - uses: rickstaa/action-create-tag@v1 id: task_release_tags_create if: ( github.event_name != 'workflow_dispatch' && inputs.DRY_RUN == false ) with: tag: "${{ env.IMAGE_VERSION }}" tag_exists_error: false message: '${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}' gpg_private_key: ${{ secrets.ADMINSERV_GPG_KEY_ASC }} gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }} # # # Job › Docker Release › Github # # job-docker-release-github: name: >- 📦 Release › Github # runs-on: ubuntu-latest runs-on: apollo-x64 timeout-minutes: 10 permissions: contents: write packages: write attestations: write id-token: write needs: [ job-docker-release-tags-create ] steps: # # # Release › Github › Start › Amd64 # # - name: '🏳️ Start' id: task_release_gh_start run: | echo "Starting Github docker release" # # # Release › Github › Checkout › Amd64 # # - name: '✅ Checkout' id: task_release_gh_checkout uses: actions/checkout@v4 # # # Release › Github › Get Timestamp # # - name: '🕛 Get Timestamp' id: task_release_set_timestamp run: | echo "IMAGE_VERSION_1DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1`" >> ${GITHUB_ENV} # 1 echo "IMAGE_VERSION_2DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-2`" >> ${GITHUB_ENV} # 1.0 echo "REGISTRY_REPO_ORG_AUTHOR_LC=`echo ${{github.repository}} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja/tvapp2 echo "REGISTRY_REPO_AUTHOR_LC=`echo ${{ env.IMAGE_GHCR_AUTHOR }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV # 71fad013cfce9116ec62779e4a7e627fe4c33627 echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV # 02-25-2025 12:49:48 echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV # 02-25-2025 echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV # 02-25-2025 12:49 echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV # 20250225 echo "NOW_DOCKER_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z # # # Release › Github › Install Dependencies # # - name: '📦 Install Dependencies' id: task_release_gh_dependencies run: sudo apt-get install -qq dos2unix # # # Release › Github › Execute dos2unix # # - name: '🔐 Apply dos2unix' id: task_release_gh_dos2unix run: | echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️" find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix -- echo "✅✅✅ Completed DOS2UNIX ✅✅✅" # # # Release › Github › Fix Permissions # # - name: '#️⃣ Manage Permissions' id: task_release_gh_permissions run: | find ./ -name 'run' -exec chmod 755 {} \; WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print) if [ -n "${WRONG_PERM}" ]; then echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️" for i in ${WRONG_PERM}; do echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!" done exit 1 else echo "✅✅✅ Executable permissions are OK ✅✅✅" fi # # # Release › Github › QEMU › Amd64 # # - name: '⚙️ Set up QEMU' id: task_release_gh_qemu uses: docker/setup-qemu-action@v3 # # # Release › Github › Setup BuildX › Amd64 # # - name: '⚙️ Setup Buildx' id: task_release_gh_buildx uses: docker/setup-buildx-action@v3 with: version: latest driver-opts: 'image=moby/buildkit:latest' # # # Release › Github › Registry Login › Amd64 # # - name: '⚙️ Login to Github' id: task_release_gh_registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ env.IMAGE_GHCR_USERNAME }} password: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }} # # # Release › Github › Meta # # - name: '🔨 Github: Meta' id: task_release_gh_meta uses: docker/metadata-action@v5 with: images: | ghcr.io/${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }} tags: | # latest yes type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }} # tag add tag type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=,event=tag # dispatch add x1.x.x type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=450,prefix=,suffix=,value=${{ env.IMAGE_VERSION }} # dispatch add x1.x type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=425,prefix=,suffix=,value=${{ env.IMAGE_VERSION_2DIGIT }} # dispatch add x1 type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=400,prefix=,suffix=,value=${{ env.IMAGE_VERSION_1DIGIT }} # dispatch add development type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=,value=development # add development tag to default architecture (amd64) type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development flavor: | latest=false labels: | org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }} org.opencontainers.image.version=${{ env.IMAGE_VERSION }} org.opencontainers.image.licenses=MIT org.opencontainers.image.revision=${{ github.sha }} org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }} org.opencontainers.image.ref.name=${{ github.ref_name }} org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }} org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}" # # # Release › Github › Build and Push › Amd64 # # - name: '📦 Build & Push (linux/amd64)' id: task_release_gh_push_amd64 uses: docker/build-push-action@v6 if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' ) with: context: . file: Dockerfile platforms: linux/amd64 push: ${{ github.event_name != 'pull_request' }} labels: ${{ steps.task_release_gh_meta.outputs.labels }} tags: | ${{ steps.task_release_gh_meta.outputs.tags }} provenance: false sbom: false build-args: |- ARCH=amd64 VERSION=${{ env.IMAGE_VERSION }} BUILDDATE=${{ env.NOW_DOCKER_LABEL }} # # # Release › Github › Build and Push › Arm64 # # - name: '📦 Build & Push (linux/arm64)' id: task_release_gh_push_arm64 uses: docker/build-push-action@v6 if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' ) with: context: . file: Dockerfile platforms: linux/arm64 push: ${{ github.event_name != 'pull_request' }} labels: ${{ steps.task_release_gh_meta.outputs.labels }} tags: | ${{ steps.task_release_gh_meta.outputs.tags }} provenance: false sbom: false build-args: |- ARCH=arm64 VERSION=${{ env.IMAGE_VERSION }} BUILDDATE=${{ env.NOW_DOCKER_LABEL }} # # # Release › Github › Push Manifest # # - name: '📦 Push Manifest' id: task_release_gh_manifest uses: int128/docker-manifest-create-action@v2 with: tags: | ${{ steps.task_release_gh_meta.outputs.tags }} sources: | ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_amd64.outputs.digest }} ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_arm64.outputs.digest }} # # # Release › Github › Checkpoint # # - name: '⚠️ Checkpoint' id: task_release_gh_checkpoint run: | echo "" echo "[ GITHUB ] ---------------------------------------------------------------------------------------------" echo "github.actor.............................. ${{ github.actor }}" echo "github.ref ............................... ${{ github.ref }}" echo "github.ref_name .......................... ${{ github.ref_name }}" echo "github.event_name ........................ ${{ github.event_name }}" echo "" echo "[ INPUTS ] ---------------------------------------------------------------------------------------------" echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}" echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}" echo "inputs.IMAGE_GHCR_AUTHOR ................. ${{ inputs.IMAGE_GHCR_AUTHOR }}" echo "inputs.IMAGE_GHCR_USERNAME ............... ${{ inputs.IMAGE_GHCR_USERNAME }}" echo "inputs.DEV_RELEASE ....................... ${{ inputs.DEV_RELEASE }}" echo "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}" echo "" echo "[ ENV ] ------------------------------------------------------------------------------------------------" echo "env.IMAGE_NAME ........................... ${{ env.IMAGE_NAME }}" echo "env.IMAGE_VERSION ........................ ${{ env.IMAGE_VERSION }}" echo "env.IMAGE_VERSION_1DIGIT ................. ${{ env.IMAGE_VERSION_1DIGIT }}" echo "env.IMAGE_VERSION_2DIGIT ................. ${{ env.IMAGE_VERSION_2DIGIT }}" echo "env.IMAGE_GHCR_AUTHOR .................... ${{ env.IMAGE_GHCR_AUTHOR }}" echo "env.IMAGE_GHCR_USERNAME .................. ${{ env.IMAGE_GHCR_USERNAME }}" echo "env.NOW .................................. ${{ env.NOW }}" echo "env.NOW_SHORT ............................ ${{ env.NOW_SHORT }}" echo "env.NOW_LONG ............................. ${{ env.NOW_LONG }}" echo "env.NOW_DOCKER_LABEL ..................... ${{ env.NOW_DOCKER_LABEL }}" echo "env.NOW_DOCKER_TS ........................ ${{ env.NOW_DOCKER_TS }}" echo "env.DOCKER_IMAGE ......................... ${{ env.DOCKER_IMAGE }}" echo "env.REGISTRY_REPO_ORG_AUTHOR_LC .......... ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}" echo "env.REGISTRY_REPO_AUTHOR_LC .............. ${{ env.REGISTRY_REPO_AUTHOR_LC }}" echo "env.DOCKER_SHA ........................... ${{ env.DOCKER_SHA }}" echo "" echo "[ DOCKER IMAGES ] --------------------------------------------------------------------------------------" echo "registry ................................. Github GHCR" echo "tags ..................................... ${{ steps.task_release_gh_meta.outputs.tags }}" echo "labels ................................... ${{ steps.task_release_gh_meta.outputs.labels }}" echo "digest ................................... ${{ steps.task_release_gh_push_amd64.outputs.digest }}" echo "" echo "(release) tags ........................... ${{ steps.task_release_gh_meta.outputs.tags }}" echo "(release) labels ......................... ${{ steps.task_release_gh_meta.outputs.labels }}" echo "" echo "[ DOCKER DIGESTS ] -------------------------------------------------------------------------------------" echo "docker image id (amd64) .................. ${{ steps.task_release_gh_push_amd64.outputs.imageid }}" echo "docker digest (amd64) .................... ${{ steps.task_release_gh_push_amd64.outputs.digest }}" echo "docker image id (arm64) .................. ${{ steps.task_release_gh_push_arm64.outputs.imageid }}" echo "docker digest (arm64) .................... ${{ steps.task_release_gh_push_arm64.outputs.digest }}" # # # Release › Github › Clean Untagged Images # # - name: '🧹 Clean Untagged Images' uses: quartx-analytics/ghcr-cleaner@v1 with: owner-type: org token: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }} repository-owner: ${{ github.repository_owner }} repository-name: ${{ github.repository }} delete-untagged: true # keep-at-most: 0 # # # Release › Github › Get Weekly Commits # # - name: '🕛 Get Weekly Commit List' id: task_release_set_weekly_commit_list run: | echo 'WEEKLY_COMMITS<> $GITHUB_ENV git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV # # # Release › Github › Notify Github # # - name: '🔔 Send Discord Webhook Message' uses: tsickert/discord-webhook@v6.0.0 if: success() with: username: 'Io' avatar-url: 'https://i.imgur.com/8BVDkla.jpg' webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES }} embed-title: "⚙️ ${{ github.workflow_ref }}" embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" embed-thumbnail-url: 'https://i.imgur.com/zDIzE8T.jpg' embed-description: | ### 📦 ᲼Deploy (Github) ᲼${{ job.status == 'success' && '✅' || '❌' }}᲼ › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}` ${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }} A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Github GHCR. The image is available at: - https://github.com/${{ github.repository }}/pkgs/container/${{ env.IMAGE_NAME }} - Version: `${{ env.IMAGE_VERSION }}` - Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}` - Pull: `docker pull ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}` - Pull (amd64): `docker pull ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_amd64.outputs.digest }}` - Pull (arm64): `docker pull ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_arm64.outputs.digest }}` - Dry Run: `${{ inputs.DRY_RUN }}` - Source: `Github` https://github.com/${{ github.repository }} - Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}` - Branch: `${{ github.ref_name }}` - Workflow: `${{ github.workflow }} (#${{github.run_number}})` - Runner: `${{ runner.name }}` - Triggered By: `${{ github.actor }}` - Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}` ### Tags -# This docker image will use the following tags: ``` ${{ steps.task_release_gh_meta.outputs.tags }} ``` ### Labels -# This docker image embeds the following labels: ``` ${{ steps.task_release_gh_meta.outputs.labels }} ``` embed-color: ${{ job.status == 'success' && '5763719' || '15418782' }} embed-footer-text: "Completed at ${{ env.NOW }} UTC" embed-timestamp: "${{ env.NOW_LONG }}" embed-author-name: "${{ github.repository_owner }}" embed-author-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" embed-author-icon-url: "https://avatars.githubusercontent.com/u/200161462"