game-ci / unity-builder

Build Unity projects for different platforms
https://github.com/marketplace/actions/unity-builder
MIT License
834 stars 238 forks source link

Running action in self-hosted runner #475

Open WildEgor opened 1 year ago

WildEgor commented 1 year ago

Bug description

When using game-ci/unity-builder@v2 on self-hosted linux docker machine some error occurs: /bin/bash: /entrypoint.sh: Is a directory Error: The process '/usr/bin/docker' failed with exit code 126

How to reproduce

  1. Use this repo https://github.com/myoung34/docker-github-actions-runner and run https://github.com/myoung34/docker-github-actions-runner/wiki/Usage docker-compose with correct envs for repo (REPO_URL, ACCESS_TOKEN); 1.1. Optionally, if docker running on Windows bind volumes like this volumes:
    • //var/run/docker.sock:/var/run/docker.sock
  2. See successfully started runner status and trigger action;
  3. When step into build see errors.

Expected behavior

Run and build

Additional details

--volume /_work/_actions/game-ci/unity-builder/v2.1.2/dist/platforms/ubuntu/entrypoint.sh:/entrypoint.sh:z unityci/editor:ubuntu-2020.3.28f1-android-1 maybe this line broken?

Brulogaz commented 1 year ago

Did anyone figure this out?

NorthIsUp commented 1 year ago

i'm getting the same issue when using act to develop locally

the docker docs seem to say that since entrypoint.sh doesn't already exist it will be created as a directory

CleanShot 2023-03-14 at 14 49 17@2x
gotchipete commented 1 year ago

i'm getting the same issue when using act to develop locally

the docker docs seem to say that since entrypoint.sh doesn't already exist it will be created as a directory CleanShot 2023-03-14 at 14 49 17@2x

seeing this also

MoonmonsterBrian commented 9 months ago

Has anyone found a solution for this?

lkkuma commented 8 months ago

So apparently this doesn't work because of the nature of "Docker in Docker" When a DinD container gets ran, its docker socket gets connected to the host, so it's only a docker client in the container that's looping back and hooking into the main docker daemon on your host.

All the files and everything definitely exist in the DinD container, but the DinD container is looking for them on the host, not in the DinD container. This isn't normally a problem for Github because they run as VMs, not as containers. This seems to be a quirk with nektos/act and I'm currently looking into a way to work around this.

lkkuma commented 7 months ago

A year later (/j, happy 2024), I come with an update. I've gotten to the point of getting a custom image with docker in docker working consistently and independently from the host. The problem I'm facing now is getting /bin/bash: line 1: /entrypoint.sh: Permission denied when actually running my workflow.

I've reached the point where I want to ask for further help here to figure this out.

Dockerfile

```Dockerfile FROM ubuntu:23.10 ARG DEBIAN_FRONTEND=noninteractive # Install core packages RUN apt-get update -y && apt-get upgrade -y \ && apt-get install -y --no-install-recommends \ sudo=\* \ curl=\* \ ca-certificates=\* \ gnupg=\* \ apt-utils=\* \ && apt-get clean && rm -rf /var/lib/apt/lists/* # Install Docker GPG keys RUN install -m 0755 -d /etc/apt/keyrings && \ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ chmod a+r /etc/apt/keyrings/docker.gpg # Add the Docker repository to Apt sources RUN echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # Install docker + other needed packages RUN apt-get update -y && apt-get upgrade -y \ && apt-get install -y --no-install-recommends \ git=\* \ git-lfs=\* \ tar=\* \ zstd=\* \ p7zip=\* \ jq=\* \ nodejs=\* \ build-essential=\* \ libssl-dev=\* \ libffi-dev=\* \ python3=\* \ python3-venv=\* \ python3-dev=\* \ python3-pip=\* \ docker-ce=\* \ docker-ce-cli=\* \ containerd.io=\* \ docker-buildx-plugin=\* \ docker-compose-plugin=\* \ && apt-get clean && rm -rf /var/lib/apt/lists/* # Add a sudo'd non-sudo user RUN useradd -m -G sudo,docker user && echo "user:user" | chpasswd RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers # Preemptively create and chown docker socket RUN touch /var/run/docker.sock && chown user:docker /var/run/docker.sock # Change to user USER user # Start the docker daemon CMD ["sudo","service","docker","start"] ```

workflow.yml

```yml name: Game autobuild on: push: tags: - "v0.0.*" paths: - ".github/**" - "projectPath/**" env: channel: "dev" unityVersion: "2021.3.30f1" projectPath: "projectPath" skipTest: true jobs: vars: runs-on: self-hosted outputs: channel: ${{ env.channel }} unityVersion: ${{ env.unityVersion }} projectPath: ${{ env.projectPath }} skipTest: ${{ env.skipTest }} steps: - name: Set vars run: | exit 0 workflow-dev-build: needs: - vars name: ${{ format('Build {0} {1}', matrix.platform, matrix.build) }} outputs: serverBuild: false strategy: fail-fast: false max-parallel: 4 matrix: platform: - "StandaloneLinux64" - "Android" - "StandaloneWindows" - "StandaloneWindows64" - "StandaloneOSX" - "iOS" build: - "client" include: - platform: "StandaloneLinux64" build: "server" runs-on: self-hosted env: library: ${{ format('{0}/Library', needs.vars.outputs.projectPath) }} targetName: ${{ format('{0}-{1}', matrix.platform, matrix.build) }} target: steps: - name: Enable docker and cgroupv2 nesting run: | sudo -s -- < /sys/fs/cgroup/init/cgroup.procs || : # enable controllers sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/cgroup.controllers \ > /sys/fs/cgroup/cgroup.subtree_control echo "Enabled cgroupv2 nesting" fi echo "Finished DinD startup" EOF - name: Determine if server or client run: | if [ '${{ matrix.build }}' == 'server' ] then echo "Target is Server" echo "target=Server" >> $GITHUB_ENV else echo "Target is Player" echo "target=Player" >> $GITHUB_ENV fi - uses: actions/checkout@v4.1.1 with: fetch-depth: 0 lfs: true # Separate step for hashing to prevent cache step failure - name: Hash projectPath for cache id: hash continue-on-error: true run: | echo "hash=${{ hashFiles(env.projectPath) }}" >> $GITHUB_OUTPUT exit 0 - uses: actions/cache@v3.3.2 with: enableCrossOsArchive: true path: ${{ env.library }} key: Library-${{ env.projectPath }}-${{ matrix.platform }}-${{ steps.hash.outputs.hash }} restore-keys: | Library-${{ env.projectPath }}-${{ matrix.platform }}- Library-${{ env.projectPath }}- Library- - if: ${{ matrix.platform == 'Android' }} name: Android cleanup uses: jlumbroso/free-disk-space@v1.3.1 - uses: game-ci/unity-builder@v4.1.3 name: Perform build id: build continue-on-error: true env: UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} with: versioning: Tag targetPlatform: ${{ matrix.platform }} unityVersion: ${{ needs.vars.outputs.unityVersion }} projectPath: ${{ env.projectPath }} buildsPath: builds buildName: ${{ matrix.platform }} runAsHostUser: true customParameters: | -standaloneBuildSubtarget ${{ env.target }} # Separate step for hashing to prevent check step failure - name: Hash build files for check id: buildHash continue-on-error: true run: | echo "hash=${{ hashFiles(format('./builds/{0}/**', matrix.platform)) }}" >> $GITHUB_OUTPUT exit 0 - name: Check if build failed if: ${{ steps.buildHash.outputs.hash == '' }} id: failCheck run: | exit 0 - uses: game-ci/unity-builder@v4.1.3 if: ${{ steps.failCheck.outcome == 'success' }} name: Retry build id: buildTwo continue-on-error: true env: UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} with: versioning: Tag targetPlatform: ${{ matrix.platform }} unityVersion: ${{ needs.vars.outputs.unityVersion }} projectPath: ${{ env.projectPath }} buildsPath: builds buildName: ${{ matrix.platform }} runAsHostUser: true cacheUnityInstallationOnMac: true customParameters: | -standaloneBuildSubtarget ${{ env.target }} - name: Zip build if: ${{ steps.build.outcome == 'success' || steps.buildTwo.outcome == 'success' }} id: zip run: | ${{ format('cd ./builds/{0}', matrix.platform) }} ${{ format('sudo 7z a -tZip {0}.zip', env.targetName) }} ls ${{ format('7z l {0}.zip', env.targetName) }} - uses: actions/upload-artifact@v4 if: ${{ steps.zip.outcome == 'success' }} id: upload with: name: ${{ format('{0}-{1}', needs.vars.outputs.channel, matrix.build) }} path: ${{ format('./builds/{0}/{0}-{1}.zip', matrix.platform, matrix.build) }} retention-days: 2 if-no-files-found: error - name: Set serverBuild output if: ${{ matrix.build == 'server' && steps.upload.outcome == 'success' }} run: | echo "serverBuild=true" >> $GITHUB_OUTPUT ```

nektos/act debug info

``` act version: 0.2.57 GOOS: windows GOARCH: amd64 NumCPU: 16 Docker host: DOCKER_HOST environment variable is not set Sockets found: \\.\pipe\docker_engine(broken) Config files: C:\Users\balan\.actrc: -P ubuntu-latest=catthehacker/ubuntu:act-latest -P ubuntu-22.04=catthehacker/ubuntu:act-22.04 -P ubuntu-20.04=catthehacker/ubuntu:act-20.04 -P ubuntu-18.04=catthehacker/ubuntu:act-18.04 .actrc: -P self-hosted=lkkuma/local-runner:latest --container-options \" --init -v GameCI-Cache:/var/lib/docker/overlay2/ \" --pull=false --no-skip-checkout --privileged --rm --container-daemon-socket=- --action-cache-path D:\.cache\act --artifact-server-path D:\.cache\actartifacts --cache-server-path D:\.cache\actcache Build info: Go version: go1.20.12 Module path: github.com/nektos/act Main version: (devel) Main path: github.com/nektos/act Main checksum: Build settings: -buildmode: exe -compiler: gc -ldflags: -s -w -X main.version=0.2.57 -X main.commit=4fae81efe4cdd9e09e7ef8e874a2d63b1ed98524 -X main.date=2024-01-01T02:17:54Z -X main.builtBy=goreleaser CGO_ENABLED: 0 GOARCH: amd64 GOOS: windows GOAMD64: v1 vcs: git vcs.revision: 4fae81efe4cdd9e09e7ef8e874a2d63b1ed98524 vcs.time: 2024-01-01T02:17:35Z vcs.modified: false Docker Engine: Engine version: 24.0.6 Engine runtime: runc Cgroup version: 2 Cgroup driver: cgroupfs Storage driver: overlay2 Registry URI: https://index.docker.io/v1/ OS: Docker Desktop OS type: linux OS version: OS arch: x86_64 OS kernel: 6.4.16-linuxkit OS CPU: 8 OS memory: 7946 MB Security options: name=seccomp,profile=unconfined name=cgroupns ```

Any extra help at this point would be fantastic.

lkkuma commented 7 months ago

I'm wondering if I have to set up docker for rootless EDIT: nevermind

WildEgor commented 7 months ago

I'm wondering if I have to set up docker for rootless EDIT: nevermind

happy 2024 :D Are you found a solution for this?

lkkuma commented 7 months ago

I'm wondering if I have to set up docker for rootless EDIT: nevermind

happy 2024 :D Are you found a solution for this?

Sorry, not yet I've burned myself out trying to figure the problem out past this point so I'm taking a small break

Oolix commented 7 months ago

I'm using windows and I was using act to attempt local runners so I didn't use up my minutes. I abandoned it comepletely. I installed WSL 2, docker-desktop and Ubuntu (wsl). I created a self hosted runner on github, ran the install commands on the ubuntu terminal and now it works!

oshaughnessy commented 7 months ago

A year later (/j, happy 2024), I come with an update. I've gotten to the point of getting a custom image with docker in docker working consistently and independently from the host. The problem I'm facing now is getting /bin/bash: line 1: /entrypoint.sh: Permission denied when actually running my workflow.

I've reached the point where I want to ask for further help here to figure this out.

@lkkuma, 2 really common reasons you'd get "permission denied" on a shell script are that the script itself is not executable, or that the reference to the script interpreter at the top of the script code does not exist (in other words, maybe your image doesn't have /bin/bash). If you're running it on Ubuntu, that shouldn't be an issue, but if you're on something smaller, like Alpine linux, you'll just want to reference /bin/sh at the top of the script instead. If the permissions are an issue, you'll want to run chmod 755 /entrypoint.sh somewhere in your Dockerfile after it's COPY'd into the image.

DakotaIrsik commented 6 months ago

I'm using windows and I was using act to attempt local runners so I didn't use up my minutes. I abandoned it comepletely. I installed WSL 2, docker-desktop and Ubuntu (wsl). I created a self hosted runner on github, ran the install commands on the ubuntu terminal and now it works!

I ended up trying this approach, but I'm having to re-run chmod or chown commands between each run, else set them in the actions file and type them as my runner terminal asks. Annoying. What am I doing wrong?

liasece commented 6 months ago

Same.

Due to the nature of DockerInDocker(dind), it is not necessary to dwell on solving this problem; here is a way to avoid similar problems:

  1. Build an actions-runner/_work directory on the host, e.g. /root/var/unity-ci/actions-runner/_work

  2. When building the game-ci container, in the Dockerfile: WORKDIR /root/var/unity-ci/

  3. To run the game-ci container, use -v /root/var/unity-ci/actions-runner/_work:/root/var/unity-ci/actions-runner/_work

The trick here is to keep the _work path in the container the same as the _work path in the host.

ReaperMaga commented 4 months ago

Any updates on this?