Rewrote license activation to use a lock to prevent race-conditions.
This commit is contained in:
@@ -1,11 +1,19 @@
|
|||||||
#Arg is replaced with the desired Unity container.
|
#Arg is replaced with the desired Unity container.
|
||||||
ARG IMAGE=unityci/editor:2023.1.16f1-windows-mono-3
|
ARG IMAGE=ubuntu:latest
|
||||||
FROM ${IMAGE}
|
FROM ${IMAGE}
|
||||||
|
|
||||||
|
ARG DOCKER_VERSION=20.10.23
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install -y software-properties-common apt-transport-https wget chromium-browser
|
RUN apt-get install -y software-properties-common apt-transport-https wget chromium-browser
|
||||||
RUN add-apt-repository -y ppa:savoury1/chromium
|
RUN add-apt-repository -y ppa:savoury1/chromium
|
||||||
RUN apt-get update && apt-get install -y chromium-browser
|
RUN apt-get update && \
|
||||||
|
apt-get install -y chromium-browser && \
|
||||||
|
apt-get install -y curl
|
||||||
|
|
||||||
|
# Install Docker CLI (static binary - much cleaner)
|
||||||
|
RUN apt-get update && apt-get install -y curl
|
||||||
|
RUN curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz | tar -xzf - --strip=1 -C /usr/local/bin docker/docker
|
||||||
|
|
||||||
#ADD https://minio.studiowhy.net/hackmd/UnityBuilder /usr/local/bin/
|
#ADD https://minio.studiowhy.net/hackmd/UnityBuilder /usr/local/bin/
|
||||||
COPY UnityBuilder /usr/local/bin/
|
COPY UnityBuilder /usr/local/bin/
|
||||||
@@ -15,10 +23,5 @@ COPY entrypoint.sh /
|
|||||||
RUN chmod +x /entrypoint.sh
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
COPY scripts/. /scripts
|
COPY scripts/. /scripts
|
||||||
# Commented out until better image selection is enabled.
|
|
||||||
# RUN --mount=type=secret,id=SERIAL \
|
|
||||||
# --mount=type=secret,id=USERNAME \
|
|
||||||
# --mount=type=secret,id=PASSWORD \
|
|
||||||
# bash /scripts/activate_license.sh
|
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|||||||
32
unity-command/acquire_lock.sh
Normal file
32
unity-command/acquire_lock.sh
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to acquire a Docker-based lock for Unity image retagging
|
||||||
|
# Usage: acquire_lock.sh <lockName>
|
||||||
|
|
||||||
|
LOCK_NAME="$1"
|
||||||
|
TIMEOUT=10
|
||||||
|
WAIT_TIME=0.2
|
||||||
|
if [ -z "$LOCK_NAME" ]; then
|
||||||
|
echo "Error: LOCK_NAME parameter is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Acquiring Docker lock '$LOCK_NAME' (timeout 10s)..."
|
||||||
|
|
||||||
|
# First, wait for any existing lock to be released
|
||||||
|
START_TS=$(date +%s)
|
||||||
|
while docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -qx "$LOCK_NAME"; do
|
||||||
|
NOW_TS=$(date +%s)
|
||||||
|
ELAPSED=$((NOW_TS - START_TS))
|
||||||
|
if [ "$ELAPSED" -ge $TIMEOUT ]; then
|
||||||
|
echo "Lock '$LOCK_NAME' still held after ${ELAPSED}s; proceeding anyway."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo "Lock '$LOCK_NAME' is held by another job. Waiting $WAIT_TIME seconds... (${ELAPSED}s elapsed)"
|
||||||
|
sleep $WAIT_TIME
|
||||||
|
done
|
||||||
|
|
||||||
|
# Now create our lock
|
||||||
|
docker pull hello-world
|
||||||
|
docker tag hello-world "$LOCK_NAME"
|
||||||
|
echo "Lock acquired: $LOCK_NAME"
|
||||||
@@ -57,18 +57,19 @@ runs:
|
|||||||
version: ${{ inputs.version }}
|
version: ${{ inputs.version }}
|
||||||
platform: ${{ inputs.platform }}
|
platform: ${{ inputs.platform }}
|
||||||
- name: "Pull Unity container."
|
- name: "Pull Unity container."
|
||||||
|
id: lock
|
||||||
run: |
|
run: |
|
||||||
|
LOCK_NAME="unity-lock:unity-lock"
|
||||||
|
echo "lockName=$LOCK_NAME" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# Acquire Docker lock for exclusive access to retag the static image
|
||||||
|
bash ${{ github.action_path }}/acquire_lock.sh "$LOCK_NAME"
|
||||||
|
|
||||||
|
IMAGE_TAG="${{ inputs.imageTag }}"
|
||||||
CONTAINER="${{ steps.getContainer.outputs.container }}"
|
CONTAINER="${{ steps.getContainer.outputs.container }}"
|
||||||
|
CACHED_CONTAINER="$CONTAINER-cached"
|
||||||
CACHED_CONTAINER="$CONTAINER-activated"
|
docker build -t "$CACHED_CONTAINER" --build-arg IMAGE="$CONTAINER" ${{ github.action_path }}
|
||||||
# Activate the license on build.
|
docker tag "$CACHED_CONTAINER" "$IMAGE_TAG"
|
||||||
# DOCKER_BUILDKIT=1 \
|
|
||||||
# SERIAL="${{ inputs.serial }}" USERNAME="${{ inputs.email }}" PASSWORD="${{ inputs.password }}" \
|
|
||||||
# docker build --secret id=SERIAL,env=SERIAL --secret id=USERNAME,env=USERNAME --secret id=PASSWORD,env=PASSWORD \
|
|
||||||
# -t $CACHED_CONTAINER --build-arg IMAGE=$CONTAINER ${{ github.action_path }}
|
|
||||||
docker build -t $CACHED_CONTAINER --build-arg IMAGE=$CONTAINER ${{ github.action_path }}
|
|
||||||
|
|
||||||
docker tag $CACHED_CONTAINER ${{ inputs.imageTag }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: "Get Unity Command."
|
- name: "Get Unity Command."
|
||||||
id: command
|
id: command
|
||||||
@@ -87,6 +88,7 @@ runs:
|
|||||||
SSH_PUBLIC_KEY: ${{ inputs.sshPublicKey }}
|
SSH_PUBLIC_KEY: ${{ inputs.sshPublicKey }}
|
||||||
SSH_PRIVATE_KEY: ${{ inputs.sshPrivateKey }}
|
SSH_PRIVATE_KEY: ${{ inputs.sshPrivateKey }}
|
||||||
CATCH_ERRORS: ${{ inputs.catchErrors }}
|
CATCH_ERRORS: ${{ inputs.catchErrors }}
|
||||||
|
LOCK_NAME: ${{ steps.lock.outputs.lockName }}
|
||||||
with:
|
with:
|
||||||
serial: ${{ inputs.serial }}
|
serial: ${{ inputs.serial }}
|
||||||
# serial: "activated"
|
# serial: "activated"
|
||||||
@@ -94,4 +96,11 @@ runs:
|
|||||||
password: ${{ inputs.password }}
|
password: ${{ inputs.password }}
|
||||||
command: ${{ steps.command.outputs.command }}
|
command: ${{ steps.command.outputs.command }}
|
||||||
unityBuilder: ${{ inputs.unityBuilder }}
|
unityBuilder: ${{ inputs.unityBuilder }}
|
||||||
|
- name: "Release Unity Docker lock."
|
||||||
|
if: ${{ always() }}
|
||||||
|
run: |
|
||||||
|
LOCK_NAME="${{ steps.lock.outputs.lockName }}"
|
||||||
|
echo "Releasing Docker lock '$LOCK_NAME'..."
|
||||||
|
docker rmi "$LOCK_NAME" >/dev/null 2>&1 || true
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
SERIAL=$1; EMAIL=$2; PASSWORD=$3; COMMAND=$4; UNITY_BUILDER=$5
|
# Accept either positional arguments or environment variables
|
||||||
|
SERIAL=${1:-$SERIAL}
|
||||||
|
EMAIL=${2:-$EMAIL}
|
||||||
|
PASSWORD=${3:-$PASSWORD}
|
||||||
|
COMMAND=${4:-$COMMAND}
|
||||||
|
UNITY_BUILDER=${5:-$UNITY_BUILDER}
|
||||||
|
|
||||||
|
# Best-effort cleanup for any Docker lock created by the composite action.
|
||||||
|
if [[ -n "$LOCK_NAME" ]]; then
|
||||||
|
echo "Removing Docker lock '$LOCK_NAME'..."
|
||||||
|
docker rmi "$LOCK_NAME" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
DEFAULT_ARGS="-quit -logFile -"
|
DEFAULT_ARGS="-quit -logFile -"
|
||||||
|
|
||||||
rm -rf $HOME/.config/unity3d
|
rm -rf $HOME/.config/unity3d
|
||||||
@@ -29,7 +41,8 @@ RESULT=$?
|
|||||||
echo "Unity command exited with code: $RESULT"
|
echo "Unity command exited with code: $RESULT"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "exitCode=$RESULT" >> "$GITHUB_OUTPUT"
|
# Uncomment if movingback to a docker action.
|
||||||
|
#echo "exitCode=$RESULT" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
if [[ "$CATCH_ERRORS" != "true" ]]; then
|
if [[ "$CATCH_ERRORS" != "true" ]]; then
|
||||||
exit $RESULT
|
exit $RESULT
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ check_path USERNAME
|
|||||||
check_path PASSWORD
|
check_path PASSWORD
|
||||||
|
|
||||||
if [[ -z "$SERIAL" || -z "$USERNAME" || -z "$PASSWORD" ]]; then
|
if [[ -z "$SERIAL" || -z "$USERNAME" || -z "$PASSWORD" ]]; then
|
||||||
|
echo "Warning: License activation skipped - missing credentials"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -25,7 +26,16 @@ fi
|
|||||||
if [[ "$SERIAL" == "personal" ]]; then
|
if [[ "$SERIAL" == "personal" ]]; then
|
||||||
echo "Obtaining personal license for Unity..."
|
echo "Obtaining personal license for Unity..."
|
||||||
UnityBuilder activate -i /usr/bin/unity-editor -u $USERNAME -p $PASSWORD
|
UnityBuilder activate -i /usr/bin/unity-editor -u $USERNAME -p $PASSWORD
|
||||||
|
ACTIVATION_RESULT=$?
|
||||||
else
|
else
|
||||||
echo "Activating Unity License with serial number."
|
echo "Activating Unity License with serial number."
|
||||||
unity-editor $DEFAULT_ARGS -serial $SERIAL -username $USERNAME -password $PASSWORD
|
unity-editor $DEFAULT_ARGS -serial $SERIAL -username $USERNAME -password $PASSWORD
|
||||||
|
ACTIVATION_RESULT=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ $ACTIVATION_RESULT -ne 0 ]]; then
|
||||||
|
echo "ERROR: Unity license activation failed with exit code $ACTIVATION_RESULT"
|
||||||
|
exit $ACTIVATION_RESULT
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Unity license activated successfully"
|
||||||
@@ -138,6 +138,16 @@ runs:
|
|||||||
fi
|
fi
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: "Upload Artifacts."
|
- name: "Upload Artifacts."
|
||||||
|
id: upload_artifacts
|
||||||
|
uses: https://github.com/ChristopherHX/gitea-upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: "${{ steps.get_product_name.outputs.nameShort }}_${{ inputs.artifactSuffix }}"
|
||||||
|
path: "${{ steps.find_output_dir.outputs.fullPath }}"
|
||||||
|
if-no-files-found: error
|
||||||
|
compression-level: ${{ inputs.compressionLevel }}
|
||||||
|
continue-on-error: true
|
||||||
|
- name: "Retry Upload Artifacts (if failed)."
|
||||||
|
if: ${{ steps.upload_artifacts.outcome == 'failure' }}
|
||||||
uses: https://github.com/ChristopherHX/gitea-upload-artifact@v4
|
uses: https://github.com/ChristopherHX/gitea-upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: "${{ steps.get_product_name.outputs.nameShort }}_${{ inputs.artifactSuffix }}"
|
name: "${{ steps.get_product_name.outputs.nameShort }}_${{ inputs.artifactSuffix }}"
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ outputs:
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
|
# Note: I may want to add the platform input to the cache key in the future if I want to cache per-platform. Though this will use more space.
|
||||||
- name: "Get full cache key and build command."
|
- name: "Get full cache key and build command."
|
||||||
id: command
|
id: command
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
Reference in New Issue
Block a user