diff --git a/.github/ps3netsrv-filter.jq b/.github/ps3netsrv-filter.jq new file mode 100644 index 00000000..678fcc94 --- /dev/null +++ b/.github/ps3netsrv-filter.jq @@ -0,0 +1,22 @@ +# Filter last five versions +def filter_last_five_versions: + .[0:5]; + +# Add tags to the first object +def add_latest_tag_to_first_object(gitref): + .[0] |= . + { "tags": (.tags + [if gitref == "main" then "latest" else "edge" end]) }; + +# Add version as tags to all objects, if it is first object then add latest +def add_version_to_tags(gitref): + .[] |= . + { "tags": (.tags + [.version + (if gitref != "main" then "-edge" else "" end)]) }; + +# Add latest commit as tags to all objects +def add_commit_to_tags(gitref): + .[] |= . + { "tags": (.tags + [(.commits | first)[:7] + (if gitref != "main" then "-edge" else "" end), (.commits | first) + (if gitref != "main" then "-edge" else "" end)]) }; + +# Add latest commit as ref +def add_latest_commit_as_ref: + .[] |= . + { "ref": (.commits | first) }; + +# Apply both filters +add_latest_commit_as_ref | filter_last_five_versions | add_version_to_tags($gitref) | add_commit_to_tags($gitref) | add_latest_tag_to_first_object($gitref) diff --git a/.github/ps3netsrv-history.json b/.github/ps3netsrv-history.json new file mode 100644 index 00000000..da185988 --- /dev/null +++ b/.github/ps3netsrv-history.json @@ -0,0 +1,272 @@ +[ + { + "version": "20250126", + "commits": [ + "bc27261a7d5b36e54c1ff0a57156bb554c441aab" + ] + }, + { + "version": "20240709", + "commits": [ + "7a36d7bf11aa8d7e6cb6e467980b70f08512dd03", + "485bf43291752656552c1d895b3263953f64cbcc" + ] + }, + { + "version": "20240707", + "commits": [ + "1d8c0c94f0d52f86edf4b9e1674d658a11f90350" + ] + }, + { + "version": "20240210a", + "commits": [ + "4ddfef91d9f4e8000dc76d48ae325533e2426a81", + "8f1e37f451e724c1932a468d8019e2844e6e90fc" + ] + }, + { + "version": "20240210", + "commits": [ + "e22b4a0edbd889d38b70f8f230886cd086a331ad", + "a0f4303ec9087c7e24de790645c71d5e2025f84b", + "96741a383934cc10d686be504e866fa6fdef9996" + ] + }, + { + "version": "20231215", + "commits": [ + "28b5bdbbd35ac6e94c262ba2b03f925646e10a25", + "ace102d14a3d06c70ed062423081f2c20cb091b8" + ] + }, + { + "version": "20220813", + "commits": [ + "5301277a0eb2275c73d7c82af9cb9e9ec34369e4" + ] + }, + { + "version": "20220421", + "commits": [ + "6d8df3595aaad324124b610dd5315f4717af5e07", + "66c4df9b0e4bea433eaba1edaafa17d9e70a521c" + ] + }, + { + "version": "20220330", + "commits": [ + "33652237e41492c2ec16e6aa3faa0807a11a440b" + ] + }, + { + "version": "20220326", + "commits": [ + "dcdffeac7aafda6af0d7f356ff17d20e6517504d", + "1a018c6141702baf904260fa9b231a0fde9dd76c" + ] + }, + { + "version": "20220301", + "commits": [ + "8c1e805c240a1a28a3c8577aeac12bedc9a4d03a", + "727f4f7d366b19c26b695ec7aab1eeec1de27669", + "5937b5c38ff0c0b7af597c57ac069bbb2c08de3a" + ] + }, + { + "version": "20220228", + "commits": [ + "2d363a436403a45c27be0a657b2e317f19c794c8" + ] + }, + { + "version": "20220227", + "commits": [ + "9344a83d90c292b3cfdef4deb91fc381ecc026a4" + ] + }, + { + "version": "20220206", + "commits": [ + "4537851d0b86f84c962d280b9ecf1bb31d32662f" + ] + }, + { + "version": "20201030", + "commits": [ + "0ad6f7409fbae854c9cc6f93d5feaa6e12a04a43", + "1b6ec2725b0d08c46acec6268948e56f3776267e", + "cce14b3587a700022ba198178b7a03fa873ce37d" + ] + }, + { + "version": "20201014", + "commits": [ + "c8079c1bc2e6a185144bee37e391c3d4bac9bb48", + "bf6a8d1ef4b870442b5c8d2276c8326fcc39a75e", + "fc5e8519f3235b339a1ea50436a85a1238c4c550", + "229f50edac6a8d9124b55d723116ba1e0fe1424a", + "d409f6af5e758517ae568ed6b8bb75d52cafb395", + "df8fdfcfed863c9b30274b9f1a50a7a432cdf84c" + ] + }, + { + "version": "20200708", + "commits": [ + "f8c6cccb71d2a65cdf1314b14521c82689d7f6c9", + "11c6e125dd64370d61f19d024047c5fd8e3affd2", + "ce356250e952097c0426d6a0626efe1dce6b412d", + "672eaf57e298f63589619a501c82b3cd7b6366e8" + ] + }, + { + "version": "20200707", + "commits": [ + "b1b9f6c606c13743a130615cb5472c1338d1ee8b" + ] + }, + { + "version": "20200704", + "commits": [ + "8e0fa2f34d6c3eb43b1ee271d910b3245f0edc45" + ] + }, + { + "version": "20200620", + "commits": [ + "4208e205b777201b40dbcc06d99b85f0072918de", + "fe030544421f58fb1b77b70b1ca0032ae4133cc7" + ] + }, + { + "version": "20200611", + "commits": [ + "a0d7ff9470d922a379e9d383e0ac619b7ca2ee44" + ] + }, + { + "version": "20200610", + "commits": [ + "b27427026a1267c3ce29b8f47435f18f9241ec24" + ] + }, + { + "version": "20200529", + "commits": [ + "6e32a14a17736421670cecbf6da7d2c749bff463", + "273b4b8b7a15d57a9fd4baeb14958d7b1f9989c5" + ] + }, + { + "version": "20200528", + "commits": [ + "c07999af7b8917edc8c2f1af8f45818be9af5fbb", + "0feb8d19eed5e2fc5b5dcbc0f69b01b48dfc2dd0" + ] + }, + { + "version": "20200527A", + "commits": [ + "c5d5dfb20d9e808a62fa0d7f911f93f6ba269c2c" + ] + }, + { + "version": "20200527", + "commits": [ + "8b285db5d4bdc98948216c990d1f0efc1e53906e" + ] + }, + { + "version": "20200525", + "commits": [ + "8c34fa967bd6bf7073b3ebc6949c9b04a0e2475d" + ] + }, + { + "version": "20200524A", + "commits": [ + "6772eb2e69c98ff346ace0eaabf8d1ded71bd8a3" + ] + }, + { + "version": "20200523", + "commits": [ + "582755aa7e9049240fce85168c46996536f9240f" + ] + }, + { + "version": "20200521", + "commits": [ + "24834d84049304e561a1aafc2636a77e679c4756" + ] + }, + { + "version": "20200520A", + "commits": [ + "7f4fdb130995b21e96a166f433001d9f0039daea", + "540f0be4b77357de78150e72e599dc6250c9263a" + ] + }, + { + "version": "20200520", + "commits": [ + "588f6e911cb69dfa9547bc2e97264696d915dc39", + "b1d9fc3715c6288b5770bbfe6fe483cbd7ec1cb4" + ] + }, + { + "version": "20200519B", + "commits": [ + "7131902f1883f0e41dda02744793c18cc9b0a7e6" + ] + }, + { + "version": "20200519A", + "commits": [ + "a8db100b81f24b2218acfa529952db83fc20cc18" + ] + }, + { + "version": "20200519", + "commits": [ + "6fcc81691a36d0d6486c6d2110c4b03571763074" + ] + }, + { + "version": "20200518", + "commits": [ + "8e69256289e986dbf561767501e4a1f64fddf63e" + ] + }, + { + "version": "20200517A", + "commits": [ + "3f3c7ed8b7d13d41ba3bb270b8b43952e7013c4f" + ] + }, + { + "version": "20200517", + "commits": [ + "a55bc2a99e865c51ebddaad508c534d1b41e3e88" + ] + }, + { + "version": "20200505", + "commits": [ + "54f5eb8a8f98ebfef79d93e3319365d3257bb5c3", + "968c9d90d67831654dd0416b2995022200e5dff8" + ] + }, + { + "version": "20190630", + "commits": [ + "cdf3d30e0205978ceb7478d65242c7bcbbbb9884", + "0ffa9f6d905169d6674b1205c323dc8adac9b56a", + "85276922fee1b3a6ef2e1b764872f31c87054e9c", + "f16dd1a10f66fadd6b5c7e7745754431159fa9d0", + "22476044db081ad00f1bbd2207280ee858b23f2d", + "ba7216db64916c41b5ab331ee00e0e74b8bef6e0" + ] + } +] diff --git a/.github/workflows/check-ps3netsrv-version.yml b/.github/workflows/check-ps3netsrv-version.yml deleted file mode 100644 index 308674c6..00000000 --- a/.github/workflows/check-ps3netsrv-version.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Update edge image -on: - schedule: - - cron: "0 1 * * *" - workflow_dispatch: -jobs: - update-version: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.REPO_SCOPED_TOKEN }} - ref: main - - name: Fetch release version - id: fetch-release - run: | - curl -sL -o release.json https://api.github.com/repos/aldostools/webMAN-MOD/releases/latest - export PS3NETSRV_VERSION=$(jq -r '[ .assets[] | select(.name | startswith("ps3netsrv")) | . ] | last | .name' release.json | \ - sed -e 's/ps3netsrv_\(.*\)\.zip/\1/') - export RELEASE_TAG=$(jq -r '.tag_name' release.json) - if [ -n "$PS3NETSRV_VERSION" ]; then - echo "Found ps3netsrv release $PS3NETSRV_VERSION" - - # replacing APP_VERSION and RELEASE_TAG in .github/workflows/docker-publish.yml - sed -ri "s/^(\s*)(APP_VERSION\s*:\s*.*\s*$)/\1APP_VERSION: \"$PS3NETSRV_VERSION\"/" .github/workflows/docker-publish.yml - sed -ri "s/^(\s*)(RELEASE_TAG\s*:\s*.*\s*$)/\1RELEASE_TAG: \"$RELEASE_TAG\"/" .github/workflows/docker-publish.yml - echo "Updated APP_VERSION with $PS3NETSRV_VERSION in .github/workflows/docker-publish.yml" - - # replacing PS3NETSRV_RELEASE and PS3NETSRV_VERSION in Dockerfile - sed -ri "s/(PS3NETSRV_VERSION=.+)/PS3NETSRV_VERSION=$PS3NETSRV_VERSION/" Dockerfile - sed -ri "s/(PS3NETSRV_RELEASE=.+)/PS3NETSRV_RELEASE=$RELEASE_TAG/" Dockerfile - echo "Updated APP_VERSION with $PS3NETSRV_VERSION in Dockerfile" - - echo ::set-output name=version::$PS3NETSRV_VERSION - echo ::set-output name=tag::$RELEASE_TAG - fi - rm -f release.json - - name: Check for modified files - id: git-check - run: echo ::set-output name=modified::$([ -z "`git status --porcelain`" ] && echo "false" || echo "true") - - name: Commit latest release version - if: steps.git-check.outputs.modified == 'true' - run: | - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git commit -am "chore: update ps3netsrv to ${{ steps.fetch-release.outputs.version }}" - git push diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 1ce393a4..f99df11f 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,40 +1,121 @@ -name: Docker +name: Docker build and publish on: + schedule: + - cron: "0 1 * * *" push: paths-ignore: - - '*.md' - - '**/*.md' - - # Publish `main` as Docker `edge` image. + - "*.md" + - "**/*.md" branches: - main - develop - - 'release/*' - - tags: - - 'v*.*.*' - - # Run tests for any PRs. pull_request: + workflow_dispatch: env: IMAGE_NAME: ps3netsrv IMAGE_TITLE: ps3netsrv IMAGE_DESCRIPTION: Docker container for ps3netsrv - APP_VERSION: "20250126" - RELEASE_TAG: "1.47.47" + IMAGE_LICENSE: gpl-3.0-or-later + ALPINE_VERSION: 3.21 + DEBIAN_VERSION: bookworm-slim + DEFAULT_BASE: alpine jobs: - # Run tests. - # See also https://docs.docker.com/docker-hub/builds/automated-testing/ - test: + update-ps3netsrv-history: runs-on: ubuntu-latest + outputs: + updated_history: ${{ steps.git-push.outputs.updated_history }} + steps: + - name: Determine branch to update + id: update-branch + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "Updating branch: ${{ github.event.pull_request.head.ref }}" + echo "branch=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT + elif [[ "${{ github.event_name }}" == "schedule" ]]; then + echo "Updating branch: ${{ github.event.repository.default_branch }}" + echo "branch=${{ github.event.repository.default_branch }}" >> $GITHUB_OUTPUT + elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "Updating branch: ${{ github.event.ref }}" + echo "branch=${{ github.event.ref }}" >> $GITHUB_OUTPUT + else + echo "Unsupported event: ${{ github.event_name }}" + exit 1 + fi + + - uses: actions/checkout@v4 + with: + token: ${{ secrets.REPO_SCOPED_TOKEN }} + ref: ${{ steps.update-branch.outputs.branch }} + - uses: actions/checkout@v4 + with: + token: ${{ secrets.REPO_SCOPED_TOKEN }} + ref: master + path: build/webman-mod + repository: aldostools/webMAN-MOD + fetch-depth: 0 + + - name: Fetch release version + id: fetch-release + run: | + echo "Gathering ps3netsrv versions per commit..." + git -C "$GITHUB_WORKSPACE/build/webman-mod" log --pretty=format:%H -- _Projects_/ps3netsrv ':(exclude,icase)_Projects_/ps3netsrv/bins/' ':(exclude,icase)_Projects_/ps3netsrv/*.md' ':(exclude,icase)_Projects_/ps3netsrv/*.txt' | \ + xargs -I {} bash -c ' + version=$(git -C "$GITHUB_WORKSPACE/build/webman-mod" show "{}:_Projects_/ps3netsrv/src/main.cpp" 2>/dev/null | sed -nr "s/.+ps3netsrv build ([0-9a-zA-Z]+).*/\1/p") + [[ -z "$version" ]] && exit + commit={} + + echo "{ \"version\": \"$version\", \"commits\": \"$commit\"}"' | \ + jq -s | \ + tee /tmp/ps3netsrv_history_raw.json + + echo "Merging ps3netsrv versions per commit..." + jq '[reduce .[] as $d (null; .[$d.version] += [$d.commits]) | to_entries | sort_by(.key) | reverse | .[] | { version: .key, commits: .value}]' /tmp/ps3netsrv_history_raw.json | tee .github/ps3netsrv-history.json + rm -rf "$GITHUB_WORKSPACE/build/webman-mod" + + - name: Check for modified files + id: git-check + run: echo "modified=$([ -z "`git status --porcelain`" ] && echo "false" || echo "true")" >> $GITHUB_OUTPUT + + - name: Commit latest release version + if: steps.git-check.outputs.modified == 'true' + id: git-push + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git commit -am "chore(history): update ps3netsrv history" + git push + echo "updated_history=true" >> $GITHUB_OUTPUT + + build-matrix: + needs: update-ps3netsrv-history + if: needs.update-ps3netsrv-history.outputs.updated_history != 'true' + runs-on: ubuntu-latest + outputs: + releases: ${{ steps.set-matrix.outputs.releases }} steps: - name: Checkout uses: actions/checkout@v4 + - name: Get latest five ps3netsrv versions + id: set-matrix + run: | + version_commit_map=$(jq -cr --arg gitref ${{ github.ref }} -f .github/ps3netsrv-filter.jq .github/ps3netsrv-history.json) + echo "version_commit_map=${version_commit_map}" + echo "releases=${version_commit_map}" >> "$GITHUB_OUTPUT" + + # Run tests build + test-build: + needs: build-matrix + strategy: + matrix: + release: ${{ fromJSON(needs.build-matrix.outputs.releases) }} + baseimage: [alpine, slim] + runs-on: ubuntu-latest + steps: - name: Set up Docker Buildx id: buildx_test uses: docker/setup-buildx-action@v3 @@ -43,22 +124,53 @@ jobs: uses: actions/cache@v4 with: path: /tmp/.test-buildx-cache - key: ${{ runner.os }}-test-buildx-${{ env.APP_VERSION }} + key: ${{ runner.os }}-test-buildx-${{ matrix.release.version }}-${{ matrix.baseimage }}-${{ github.ref }} restore-keys: | - ${{ runner.os }}-test-buildx-${{ env.APP_VERSION }} - ${{ runner.os }}-test-buildx- + ${{ runner.os }}-test-buildx-${{ matrix.release.version }}-${{ matrix.baseimage }}-${{ github.ref }} + ${{ runner.os }}-test-buildx-${{ github.ref }} + + - name: Checkout + uses: actions/checkout@v4 + + - name: Test tag splitting + env: + PS3NETSRV_VERSION: ${{ matrix.release.version }} + PS3NETSRV_SRC_REF: ${{ matrix.release.ref }} + PS3NETSRV_COMMITS: ${{ join(matrix.release.commits, ',') }} + PS3NETSRV_TAGS: ${{ join(matrix.release.tags, ',') }} + run: | + DOCKERIO_IMAGE=docker.io/${{ github.repository_owner }}/$IMAGE_NAME + GHCRIO_IMAGE=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME + + # Split PS3NETSRV_TAGS by commata + IFS=, read -r -a TAGS <<< "$PS3NETSRV_TAGS" + + echo "Would create tags:" + for TAG in "${TAGS[@]}"; do + DOCKERIO_TAGS="${DOCKERIO_TAGS},${DOCKERIO_IMAGE}:${TAG}-${{ matrix.baseimage }}" + GHCRIO_TAGS="${GHCRIO_TAGS},${GHCRIO_IMAGE}:${TAG}-${{ matrix.baseimage }}" + # If default base we also tag the image without the base name + if [[ ${{ matrix.baseimage }} == $DEFAULT_BASE ]]; then + DOCKERIO_TAGS="${DOCKERIO_TAGS},${DOCKERIO_IMAGE}:${TAG}" + GHCRIO_TAGS="${GHCRIO_TAGS},${GHCRIO_IMAGE}:${TAG}" + fi + done + echo "DOCKERIO_TAGS=${DOCKERIO_TAGS:-}" + echo "GHCRIO_TAGS=${GHCRIO_TAGS:-}" - name: Test build - id: docker_build_test uses: docker/build-push-action@v6 with: builder: ${{ steps.buildx_test.outputs.name }} - context: . + file: ${{ matrix.baseimage }}.Dockerfile platforms: linux/amd64 push: false + load: true build-args: | - PS3NETSRV_RELEASE=${{ env.RELEASE_TAG }} - PS3NETSRV_VERSION=${{ env.APP_VERSION }} + BUILD_FROM_GIT=true + PS3NETSRV_VERSION=${{ matrix.release.version }} + PS3NETSRV_SRC_REF=${{ matrix.release.ref }} + tags: ps3netsrv:test-build-${{ matrix.release.version }}-${{ matrix.baseimage }} cache-from: type=local,src=/tmp/.test-buildx-cache cache-to: type=local,dest=/tmp/.test-buildx-cache-new @@ -70,13 +182,43 @@ jobs: rm -rf /tmp/.test-buildx-cache mv /tmp/.test-buildx-cache-new /tmp/.test-buildx-cache + - name: Create ps3netsrv container... + run: | + echo "Changing permissions for tests/games..." + sudo bash tests/setup-test-structure.sh + echo "Starting ps3netsrv container..." + docker run -t -d --name ps3netsrv-test -e PS3NETSRV_FIX_PERMISSIONS=true -v ./tests/games:/games ps3netsrv:test-build-${{ matrix.release.version }}-${{ matrix.baseimage }} + echo "Trying 30 seconds to check for startup..." + count=0 + exitcode=1 + while [ $count -lt 30 ]; do + if docker logs ps3netsrv-test | grep "ps3netsrv build ${{ matrix.release.version }}" >/dev/null; then + docker logs ps3netsrv-test + echo "Success!" + exitcode=0 + break + else + echo "Waiting for ps3netsrv to start... $(docker logs ps3netsrv-test)" + exitcode=1 + fi + sleep 1 + count=$((count + 1)) + done + + docker stop ps3netsrv-test >/dev/null + exit "$exitcode" + # Build images. build: if: github.event_name != 'pull_request' runs-on: ubuntu-latest - - needs: test - + outputs: + publish: ${{ steps.prep.outputs.publish }} + readme_tags: ${{ steps.prep.outputs.readme_tags }} + needs: [build-matrix, test-build] + strategy: + matrix: + release: ${{ fromJSON(needs.build-matrix.outputs.releases) }} steps: - name: Checkout uses: actions/checkout@v4 @@ -105,63 +247,45 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Prepare + - name: Prepare variables id: prep + env: + PS3NETSRV_VERSION: ${{ matrix.release.version }} + PS3NETSRV_SRC_REF: ${{ matrix.release.ref }} + PS3NETSRV_COMMITS: ${{ join(matrix.release.commits, ',') }} + PS3NETSRV_TAGS: ${{ join(matrix.release.tags, ',') }} run: | DOCKERIO_IMAGE=docker.io/${{ github.repository_owner }}/$IMAGE_NAME GHCRIO_IMAGE=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME - # Strip git ref prefix from version - VERSION_FULL=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\)$,\1,') - VERSION_MINOR=$(echo "$VERSION_FULL" | sed 's,\.[^.]*$,,') - VERSION_MAJOR=$(echo "$VERSION_MINOR" | sed 's,\.[^.]*$,,') - - # Use Docker `edge` tag convention and pr- for pull requests - [ "$VERSION_FULL" == "main" ] && VERSION_FULL=edge - [ ${{ github.ref }} == refs/pull/* ] && VERSION_FULL=pr-${{ github.event.number }} - - # Build all tags - DOCKERIO_TAGS="${DOCKERIO_IMAGE}:${VERSION_FULL}" - [ "$VERSION_FULL" != "edge" ] && DOCKERIO_TAGS="$DOCKERIO_TAGS,${DOCKERIO_IMAGE}:${VERSION_MINOR},${DOCKERIO_IMAGE}:${VERSION_MAJOR},${DOCKERIO_IMAGE}:${APP_VERSION},${DOCKERIO_IMAGE}:latest" - [ "$VERSION_FULL" == "edge" ] && DOCKERIO_TAGS="$TAGS,${DOCKERIO_IMAGE}:${VERSION_FULL}-${APP_VERSION}" - GHCRIO_TAGS="${GHCRIO_IMAGE}:${VERSION_FULL}" - [ "$VERSION_FULL" != "edge" ] && GHCRIO_TAGS="$GHCRIO_TAGS,${GHCRIO_IMAGE}:${VERSION_MINOR},${GHCRIO_IMAGE}:${VERSION_MAJOR},${GHCRIO_IMAGE}:${APP_VERSION},${GHCRIO_IMAGE}:latest" - [ "$VERSION_FULL" == "edge" ] && GHCRIO_TAGS="$GHCRIO_TAGS,${GHCRIO_IMAGE}:${VERSION_FULL}-${APP_VERSION}" - - # Build tags for README.md - [ "$VERSION_FULL" != "edge" ] && README_TAGS="\`latest\`, \`${VERSION_MAJOR}\`, \`${VERSION_MINOR}\`, \`${VERSION_FULL}\`, \`${APP_VERSION}\`" - [ "$VERSION_FULL" == "edge" ] && README_TAGS="\`${VERSION_FULL}\`, \`${VERSION_FULL}-${APP_VERSION}\`" - - # Replace supported latest tags in README.md - if [ "$VERSION_FULL" != "edge" ]; then - sed -i '/- `latest`.*/c- '"${README_TAGS}"' ' README.md - fi - # Replace supported edge tags in README.md - if [ "$VERSION_FULL" == "edge" ]; then - sed -i '/- `edge`.*/c- '"${README_TAGS}"' ' README.md - fi - - # Use Docker `edge` tag convention and pr- for pull requests - [ "$VERSION_FULL" == "main" ] && VERSION_FULL=edge - [ ${{ github.ref }} == refs/pull/* ] && VERSION_FULL=pr-${{ github.event.number }} - - # Build tags for README.md - [ "$VERSION_FULL" != "edge" ] && README_TAGS="\`latest\`, \`${VERSION_MAJOR}\`, \`${VERSION_MINOR}\`, \`${VERSION_FULL}\`, \`${APP_VERSION}\`" - [ "$VERSION_FULL" == "edge" ] && README_TAGS="\`${VERSION_FULL}\`, \`${VERSION_FULL}-${APP_VERSION}\`" - - echo "version=${VERSION_FULL}" >> $GITHUB_OUTPUT + # Split PS3NETSRV_TAGS by commata + IFS=, read -r -a TAGS <<< "$PS3NETSRV_TAGS" + + for TAG in "${TAGS[@]}"; do + DOCKERIO_TAGS="${DOCKERIO_TAGS},${DOCKERIO_IMAGE}:${TAG}-${{ matrix.baseimage }}" + GHCRIO_TAGS="${GHCRIO_TAGS},${GHCRIO_IMAGE}:${TAG}-${{ matrix.baseimage }}" + README_TAGS="${README_TAGS}, \`${TAG}-${{ matrix.baseimage }}\`" + # If default base we also tag the image without the base name + if [[ ${{ matrix.baseimage }} == $DEFAULT_BASE ]]; then + DOCKERIO_TAGS="${DOCKERIO_TAGS},${DOCKERIO_IMAGE}:${TAG}" + GHCRIO_TAGS="${GHCRIO_TAGS},${GHCRIO_IMAGE}:${TAG}" + README_TAGS="${README_TAGS}, \`${TAG}\`" + fi + done + + echo "version=${PS3NETSRV_VERSION}" >> $GITHUB_OUTPUT echo "tags=${DOCKERIO_TAGS},${GHCRIO_TAGS}" >> $GITHUB_OUTPUT - echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT echo "readme_tags=${README_TAGS}" >> $GITHUB_OUTPUT - echo "release=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags') }}" >> $GITHUB_OUTPUT + echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT + echo "publish=${{ github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags') }}" >> $GITHUB_OUTPUT - name: Cache Docker layers uses: actions/cache@v4 with: path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ env.APP_VERSION }} + key: ${{ runner.os }}-buildx-${{ matrix.release.version }} restore-keys: | - ${{ runner.os }}-buildx-${{ env.APP_VERSION }} + ${{ runner.os }}-buildx-${{ matrix.release.version }} ${{ runner.os }}-buildx- - name: Build and push @@ -169,48 +293,87 @@ jobs: uses: docker/build-push-action@v6 with: builder: ${{ steps.buildx.outputs.name }} - context: . - platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6 - push: ${{ steps.prep.outputs.release == 'true' }} + file: ${{ matrix.baseimage }}.Dockerfile + platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 + push: ${{ steps.prep.outputs.publish == 'true' }} tags: ${{ steps.prep.outputs.tags }} build-args: | - PS3NETSRV_RELEASE=${{ env.RELEASE_TAG }} - PS3NETSRV_VERSION=${{ env.APP_VERSION }} + BUILD_FROM_GIT=true + PS3NETSRV_VERSION=${{ matrix.release.version }} + PS3NETSRV_SRC_REF=${{ matrix.release.ref }} labels: | - org.opencontainers.image.title=$IMAGE_TITLE - org.opencontainers.image.description=$IMAGE_DESCRIPTION + org.opencontainers.image.title=${{ env.IMAGE_TITLE }} + org.opencontainers.image.description=${{ env.IMAGE_DESCRIPTION }} org.opencontainers.image.vendor=${{ github.repository_owner }} org.opencontainers.image.url=${{ github.event.repository.html_url }} org.opencontainers.image.source=${{ github.event.repository.html_url }} org.opencontainers.image.created=${{ steps.prep.outputs.created }} - org.opencontainers.image.revision=${{ github.sha }} - org.opencontainers.image.version=$APP_VERSION + org.opencontainers.image.revision=${{ matrix.release.ref }} + org.opencontainers.image.version=${{ matrix.release.version }} + org.opencontainers.image.licenses=${{ env.IMAGE_LICENSE }} + annotations: | + org.opencontainers.image.title=${{ env.IMAGE_TITLE }} + org.opencontainers.image.description=${{ env.IMAGE_DESCRIPTION }} + org.opencontainers.image.vendor=${{ github.repository_owner }} + org.opencontainers.image.url=${{ github.event.repository.html_url }} + org.opencontainers.image.source=${{ github.event.repository.html_url }} + org.opencontainers.image.created=${{ steps.prep.outputs.created }} + org.opencontainers.image.revision=${{ matrix.release.ref }} + org.opencontainers.image.version=${{ matrix.release.version }} + org.opencontainers.image.licenses=${{ env.IMAGE_LICENSE }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new + # Temp fix + # https://github.com/docker/build-push-action/issues/252 + # https://github.com/moby/buildkit/issues/1896 + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache + + update-readme: + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + needs: [build-matrix, build] + steps: - name: Checkout main - if: steps.prep.outputs.release == 'true' + if: needs.build.outputs.publish == 'true' uses: actions/checkout@v4 with: ref: main - - name: Update README.md - if: steps.prep.outputs.release == 'true' - id: update-readme + - name: Set start and end comment + if: needs.build.outputs.publish == 'true' + id: comment run: | - # Replace supported latest tags in README.md - if [ "${{ steps.prep.outputs.version }}" != "edge" ]; then - sed -i '/- `latest`.*/c- ${{ steps.prep.outputs.readme_tags }} ' README.md - fi - # Replace supported edge tags in README.md - if [ "${{ steps.prep.outputs.version }}" == "edge" ]; then - sed -i '/- `edge`.*/c- ${{ steps.prep.outputs.readme_tags }} ' README.md + # Replace supported tags in README.md + # Define the start and end comments in the README.md file + if [ "${{ github.ref }}" != "refs/heads/main" ]; then + echo 'start_comment=' >> "$GITHUB_OUTPUT" + echo 'end_comment=' >> "$GITHUB_OUTPUT" + else + echo 'start_comment=' >> "$GITHUB_OUTPUT" + echo 'end_comment=' >> "$GITHUB_OUTPUT" fi + - name: Prepare variables + if: needs.build.outputs.publish == 'true' + id: prep + run: | + README_TAGS=$(jq -r '"- " + (.[] | [.tags[] | "`" + . + "`"] | join(", "))' <<< '${{ needs.build-matrix.outputs.releases }}') + + # Cleanout space between start and end comment + sed -i '/${{ steps.comment.outputs.start_comment }}/,/${{ steps.comment.outputs.end_comment }}/ { //!d }' README.md + + # Replace the tags + sed -i "\\~${{ steps.comment.outputs.start_comment }}~,\\~${{ steps.comment.outputs.end_comment }}~ { \\|${{ steps.comment.outputs.start_comment }}|r /dev/stdin + }" README.md <<< "$README_TAGS" + - name: Check for modified files - if: steps.prep.outputs.release == 'true' + if: needs.build.outputs.publish == 'true' id: git-check - run: echo modified=$([ -z "`git status --porcelain`" ] && echo "false" || echo "true") >> $GITHUB_OUTPUT + run: echo "modified=$([ -z "`git status --porcelain`" ] && echo "false" || echo "true")" >> $GITHUB_OUTPUT - name: Commit updated README.md if: steps.git-check.outputs.modified == 'true' @@ -220,11 +383,3 @@ jobs: git add README.md git commit -m "docs(README): update supported tags" git push - - # Temp fix - # https://github.com/docker/build-push-action/issues/252 - # https://github.com/moby/buildkit/issues/1896 - - name: Move cache - run: | - rm -rf /tmp/.buildx-cache - mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/.gitignore b/.gitignore index e69de29b..961251bf 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,2 @@ +games/ +build/ diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4f3af4bf..00000000 --- a/Dockerfile +++ /dev/null @@ -1,157 +0,0 @@ -# -# ps3netsrv Dockerfile -# -# https://github.com/shawly/docker-ps3netsrv -# - -# Set alpine version -ARG ALPINE_VERSION=3.18 - -# Set vars for s6 overlay -ARG S6_OVERLAY_VERSION=v2.2.0.3 -ARG S6_OVERLAY_BASE_URL=https://github.com/just-containers/s6-overlay/releases/download/${S6_OVERLAY_VERSION} - -# Set PS3NETSRV vars -ARG PS3NETSRV_REPO=https://github.com/aldostools/webMAN-MOD.git -ARG PS3NETSRV_DIR=_Projects_/ps3netsrv -ARG PS3NETSRV_REF=master -ARG BUILD_FROM_GIT=false - -ARG PS3NETSRV_RELEASE=1.47.47 -ARG PS3NETSRV_VERSION=20250126 -ARG PS3NETSRV_URL=https://github.com/aldostools/webMAN-MOD/releases/download/${PS3NETSRV_RELEASE}/ps3netsrv_${PS3NETSRV_VERSION}.zip - -# Set base images with s6 overlay download variable (necessary for multi-arch building via GitHub workflows) -FROM alpine:${ALPINE_VERSION} as alpine-amd64 - -ARG S6_OVERLAY_VERSION -ARG S6_OVERLAY_BASE_URL -ENV S6_OVERLAY_RELEASE="${S6_OVERLAY_BASE_URL}/s6-overlay-amd64.tar.gz" - -FROM alpine:${ALPINE_VERSION} as alpine-386 - -ARG S6_OVERLAY_VERSION -ARG S6_OVERLAY_BASE_URL -ENV S6_OVERLAY_RELEASE="${S6_OVERLAY_BASE_URL}/s6-overlay-x86.tar.gz" - -FROM alpine:${ALPINE_VERSION} as alpine-armv6 - -ARG S6_OVERLAY_VERSION -ARG S6_OVERLAY_BASE_URL -ENV S6_OVERLAY_RELEASE="${S6_OVERLAY_BASE_URL}/s6-overlay-armhf.tar.gz" - -FROM alpine:${ALPINE_VERSION} as alpine-armv7 - -ARG S6_OVERLAY_VERSION -ARG S6_OVERLAY_BASE_URL -ENV S6_OVERLAY_RELEASE="${S6_OVERLAY_BASE_URL}/s6-overlay-arm.tar.gz" - -FROM alpine:${ALPINE_VERSION} as alpine-arm64 - -ARG S6_OVERLAY_VERSION -ARG S6_OVERLAY_BASE_URL -ENV S6_OVERLAY_RELEASE="${S6_OVERLAY_BASE_URL}/s6-overlay-aarch64.tar.gz" - -FROM alpine:${ALPINE_VERSION} as alpine-ppc64le - -ARG S6_OVERLAY_VERSION -ARG S6_OVERLAY_BASE_URL -ENV S6_OVERLAY_RELEASE="${S6_OVERLAY_BASE_URL}/s6-overlay-ppc64le.tar.gz" - -# Build ps3netsrv:master -FROM alpine:${ALPINE_VERSION} as builder - -ARG PS3NETSRV_REPO -ARG PS3NETSRV_DIR -ARG PS3NETSRV_REF -ARG PS3NETSRV_RELEASE -ARG PS3NETSRV_VERSION -ARG PS3NETSRV_URL -ARG BUILD_FROM_GIT - -# Change working dir -WORKDIR /tmp - -# Install deps and build binary -RUN \ - set -ex && \ - echo "Installing build dependencies..." && \ - apk add --update --no-cache \ - curl \ - git \ - build-base \ - meson \ - mbedtls-dev \ - musl \ - musl-dev \ - musl-dbg \ - musl-utils \ - tar \ - unzip - -RUN \ - [ "${BUILD_FROM_GIT:-}" != "true" ] || (echo "Building ps3netsrv from git repo (ref: ${PS3NETSRV_REF})..." && \ - git clone --depth 1 "${PS3NETSRV_REPO}" --branch "${PS3NETSRV_REF}" repo && \ - cd /tmp/repo/${PS3NETSRV_DIR} && \ - meson build --buildtype=release && \ - ninja -C build/ && \ - mkdir -p /tmp/ps3netsrv-bin && \ - cp -v /tmp/repo/${PS3NETSRV_DIR}/build/ps3netsrv /tmp/ps3netsrv-bin/) - -RUN \ - [ "${BUILD_FROM_GIT:-}" == "true" ] || (echo "Building ps3netsrv from release (ps3netsrv_${PS3NETSRV_VERSION}.zip)..." && \ - curl -sL --output /tmp/ps3netsrv.zip "${PS3NETSRV_URL}" && \ - unzip /tmp/ps3netsrv.zip -d /tmp && \ - find "/tmp" -type d -maxdepth 1 -iname "*ps3netsrv_*" -exec mv -f {} "/tmp/ps3netsrv" \; && \ - cd /tmp/ps3netsrv/ps3netsrv && \ - meson build --buildtype=release && \ - ninja -C build/ && \ - mkdir -p /tmp/ps3netsrv-bin && \ - cp -v build/ps3netsrv /tmp/ps3netsrv-bin/) - -# Runtime container -FROM alpine-${TARGETARCH:-amd64}${TARGETVARIANT} - -# Download s6 overlay -ADD ${S6_OVERLAY_RELEASE} /tmp/s6overlay.tar.gz - -# Copy binary from build container -COPY --from=builder /tmp/ps3netsrv-bin/ps3netsrv /usr/local/bin/ps3netsrv - -# Install runtime deps and add users -RUN \ - set -ex && \ - echo "Installing runtime dependencies..." && \ - apk add --no-cache \ - bash \ - coreutils \ - shadow \ - tzdata \ - libstdc++ \ - musl \ - musl-utils \ - mbedtls && \ - echo "Extracting s6 overlay..." && \ - tar xzf /tmp/s6overlay.tar.gz -C / && \ - echo "Creating ps3netsrv user..." && \ - useradd -u 1000 -U -M -s /bin/false ps3netsrv && \ - usermod -G users ps3netsrv && \ - mkdir -p /var/log/ps3netsrv && \ - chown -R nobody:nogroup /var/log/ps3netsrv && \ - echo "Cleaning up temp directory..." && \ - rm -rf /tmp/* - -# Add files -COPY rootfs/ / - -ENV PS3NETSRV_PORT=38008 \ - PS3NETSRV_WHITELIST= - -# Define mountable directories -VOLUME ["/games"] - -# Expose ports -EXPOSE 38008 - -# Start s6 -ENTRYPOINT ["/init"] diff --git a/Dockerfile b/Dockerfile new file mode 120000 index 00000000..53292c56 --- /dev/null +++ b/Dockerfile @@ -0,0 +1 @@ +alpine.Dockerfile \ No newline at end of file diff --git a/README.md b/README.md index ceed28cc..c576c923 100644 --- a/README.md +++ b/README.md @@ -70,11 +70,9 @@ The architectures supported by this image are: | Architecture | Status | | :----------: | --------------------------------------------------------------- | | x86-64 | working | -| x86 | untested | | arm64 | [working](https://github.com/shawly/docker-ps3netsrv/issues/19) | | armv7 | untested | | armhf | working | -| ~ppc64le~ | dropped | _I'm declaring the arm images as **untested** because I only own an older first generation RaspberryPi Model B+ I can't properly test the image on other devices, technically it should work on all RaspberryPi models and similar SoCs. While emulating the architecture with qemu works and can be used for testing, I can't guarantee that there will be no issues, just try it._ @@ -88,7 +86,7 @@ and parameters should be adjusted to your need. Launch the ps3netsrv docker container with the following command: ``` -docker run -d \ +docker run -d -t \ --name=ps3netsrv \ -p 38008:38008 \ -v $HOME/ps3games:/games:rw \ @@ -102,7 +100,7 @@ Where: ## Usage ``` -docker run [-d] \ +docker run [-d] -t \ --name=ps3netsrv \ [-e =]... \ [-v :[:PERMISSIONS]]... \ @@ -125,8 +123,8 @@ of this parameter has the format `=`. | Variable | Description | Default | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------- | -| `USER_ID` | ID of the user the application runs as. See [User/Group IDs](#usergroup-ids) to better understand when this should be set. | `1000` | -| `GROUP_ID` | ID of the group the application runs as. See [User/Group IDs](#usergroup-ids) to better understand when this should be set. | `1000` | +| `PUID` | ID of the user the application runs as. See [User/Group IDs](#usergroup-ids) to better understand when this should be set. | `1000` | +| `PGID` | ID of the group the application runs as. See [User/Group IDs](#usergroup-ids) to better understand when this should be set. | `1000` | | `PS3NETSRV_PORT` | Port used by ps3netsrv. You only need to change this when using network_mode host, otherwise you can just remap ports using Docker! | `38008` | | `PS3NETSRV_WHITELIST` | Whitelist IPs e.g. `192.168.1.*` or `192.168.1.10-192.168.1.200`, this probably only works with network_mode host! | `` | | `TZ` | [TimeZone] of the container. Timezone can also be set by mapping `/etc/localtime` between the host and the container. | `Etc/UTC` | @@ -189,10 +187,12 @@ version: "3" services: ps3netsrv: image: shawly/ps3netsrv:latest + restart: unless-stopped + tty: true environment: TZ: Europe/Berlin - USER_ID: 38008 # change this to the uid of the user that owns your games folder - GROUP_ID: 38008 # change this to the gid of the user that owns your games folder + PUID: 38008 # change this to the uid of the user that owns your games folder + PGID: 38008 # change this to the gid of the user that owns your games folder ports: - "38008:38008" volumes: @@ -234,7 +234,7 @@ and folders on the shared volume. To avoid any problem, you can specify the user the application should run as. This is done by passing the user ID and group ID to the container via the -`USER_ID` and `GROUP_ID` environment variables. +`PUID` and `PGID` environment variables. To find the right IDs to use, issue the following command on the host, with the user owning the data volume on the host: @@ -276,7 +276,7 @@ docker run -d \ ps3netsrv does not have root permissions within the container, it runs as user `ps3netsrv` which by default has the UID 1000 and the GID 1000. There are two solutions for this issue, `bob` could change the ownership of his `ps3games` folder to 1000:1000, which is a bad idea because he will lose access if he does not have the UID 1000. -The better solution is to override the `ps3netsrv` user's UID and GID, this can be done with the environment variables `USER_ID` and `GROUP_ID`. +The better solution is to override the `ps3netsrv` user's UID and GID, this can be done with the environment variables `PUID` and `PGID`. `bob` has the UID 10002 and his `bob` group has the GID 10003 so we need to change the environment variables, like this: ``` @@ -284,8 +284,8 @@ docker run -d \ --name=ps3netsrv \ -p 38008:38008 \ -v $HOME/ps3games:/games:rw \ - -e USER_ID=10002 \ - -e GROUP_ID=10003 \ + -e PUID=10002 \ + -e PGID=10003 \ shawly/ps3netsrv ``` diff --git a/alpine.Dockerfile b/alpine.Dockerfile new file mode 100644 index 00000000..a9ad7fc3 --- /dev/null +++ b/alpine.Dockerfile @@ -0,0 +1,170 @@ +# +# ps3netsrv Dockerfile +# +# https://github.com/shawly/docker-ps3netsrv +# + +# Set alpine version +ARG ALPINE_VERSION=3.21 + +# Set vars for s6 overlay +ARG S6_OVERLAY_RELEASE=v3.2.0.2 +ARG S6_OVERLAY_ARCH=x86_64 +ARG S6_OVERLAY_DOWNLOAD_URL=https://github.com/just-containers/s6-overlay/releases/download + +# Set PS3NETSRV vars +ARG PS3NETSRV_REPO=https://github.com/aldostools/webMAN-MOD.git +ARG PS3NETSRV_SRC_DIR=_Projects_/ps3netsrv +ARG PS3NETSRV_SRC_REF=master +ARG BUILD_FROM_GIT=true + +ARG PS3NETSRV_VERSION +ARG PS3NETSRV_GITHUB_API_URL=https://api.github.com/repos/aldostools/webMAN-MOD/releases + +# Set base images with s6 overlay download variable (necessary for multi-arch building via GitHub workflows) +FROM alpine:${ALPINE_VERSION} AS alpine-amd64 + +ARG S6_OVERLAY_ARCH=x86_64 + +FROM alpine:${ALPINE_VERSION} AS alpine-armv6 + +ARG S6_OVERLAY_ARCH=armhf + +FROM alpine:${ALPINE_VERSION} AS alpine-armv7 + +ARG S6_OVERLAY_ARCH=arm + +FROM alpine:${ALPINE_VERSION} AS alpine-arm64 + +ARG S6_OVERLAY_ARCH=aarch64 + +# Build ps3netsrv:master +FROM alpine:${ALPINE_VERSION} AS builder + +ARG PS3NETSRV_REPO +ARG PS3NETSRV_SRC_DIR +ARG PS3NETSRV_SRC_REF +ARG PS3NETSRV_GITHUB_API_URL +ARG PS3NETSRV_VERSION +ARG BUILD_FROM_GIT + +# Change working dir +WORKDIR /tmp + +# Install deps and build binary +RUN \ + set -e && \ + echo "Installing build dependencies..." && \ + apk add --update --no-cache \ + curl \ + jq \ + git \ + build-base \ + meson \ + mbedtls-dev \ + musl \ + musl-dev \ + musl-dbg \ + musl-utils \ + tar \ + unzip + +# Set CFLAGS to define _LARGEFILE64_SOURCE +ARG CFLAGS="-D_LARGEFILE64_SOURCE" +ARG CPPFLAGS="-D_LARGEFILE64_SOURCE" + +RUN \ + [ "${BUILD_FROM_GIT:-}" != "true" ] || (echo "Building ps3netsrv from git repo (ref: ${PS3NETSRV_SRC_REF:?})..." && \ + mkdir -p /tmp/repo/ && \ + cd /tmp/repo/ && \ + git init && \ + git remote add origin "${PS3NETSRV_REPO:?}" && \ + git fetch --depth 1 origin "${PS3NETSRV_SRC_REF:?}" && \ + git checkout FETCH_HEAD && \ + cd /tmp/repo/${PS3NETSRV_SRC_DIR:?} && \ + meson build --buildtype=release && \ + ninja -C build/ && \ + mkdir -p /tmp/ps3netsrv-bin && \ + cp -v /tmp/repo/${PS3NETSRV_SRC_DIR:?}/build/ps3netsrv /tmp/ps3netsrv-bin/ps3netsrv-mbedtls && \ + make -f Makefile.linux && \ + cp -v ./ps3netsrv /tmp/ps3netsrv-bin/ps3netsrv-polarssl) + +RUN \ + [ "${BUILD_FROM_GIT:-}" == "true" ] || (echo "Building ps3netsrv from release (ps3netsrv_${PS3NETSRV_VERSION:?}.zip)..." && \ + cd /tmp && \ + echo "Getting releases from ${PS3NETSRV_GITHUB_API_URL:?}" && \ + curl -sL -o releases.json "${PS3NETSRV_GITHUB_API_URL:?}" && \ + PS3NETSRV_URL="$(jq -r --arg version "${PS3NETSRV_VERSION:?}" '[.[].assets[] | select(.name | startswith("ps3netsrv_" + $version)) | .browser_download_url] | first' releases.json)" && \ + echo "Downloading release from ${PS3NETSRV_URL:?}" && \ + curl -sL --output /tmp/ps3netsrv.zip "${PS3NETSRV_URL:?}" && \ + echo "Extracting release..." && \ + unzip /tmp/ps3netsrv.zip -d /tmp && \ + find "/tmp" -type d -maxdepth 1 -iname "*ps3netsrv_*" -exec mv -f {} "/tmp/ps3netsrv" \; && \ + cd /tmp/ps3netsrv/ps3netsrv && \ + echo "Building release..." && \ + meson build --buildtype=release && \ + ninja -C build/ && \ + mkdir -p /tmp/ps3netsrv-bin && \ + cp -v build/ps3netsrv /tmp/ps3netsrv-bin/ps3netsrv-mbedtls && \ + echo "Building alternative with POLARSSL instead of mbedTLS..." && \ + make -f Makefile.linux && \ + mkdir -p /tmp/ps3netsrv-bin && \ + cp -v ./ps3netsrv /tmp/ps3netsrv-bin/ps3netsrv-polarssl) + +# Runtime container +FROM alpine-${TARGETARCH:-amd64}${TARGETVARIANT} + +ARG S6_OVERLAY_RELEASE +ARG S6_OVERLAY_ARCH +ARG S6_OVERLAY_DOWNLOAD_URL + +# Add s6-overlay files +ADD ${S6_OVERLAY_DOWNLOAD_URL}/${S6_OVERLAY_RELEASE}/s6-overlay-noarch.tar.xz /tmp +ADD ${S6_OVERLAY_DOWNLOAD_URL}/${S6_OVERLAY_RELEASE}/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz /tmp + +# Copy binary from build container +COPY --from=builder /tmp/ps3netsrv-bin/ps3netsrv* /usr/bin/ + +# Install runtime deps and add users +RUN \ + set -e && \ + echo "Installing runtime dependencies..." && \ + apk add --no-cache \ + bash \ + coreutils \ + shadow \ + tzdata \ + libstdc++ \ + musl \ + musl-utils \ + mbedtls \ + xz && \ + echo "Extracting s6 overlay..." && \ + tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz && \ + tar -C / -Jxpf /tmp/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz && \ + echo "Creating ps3netsrv user..." && \ + useradd -u 1000 -U -M -s /bin/false ps3netsrv && \ + usermod -G users ps3netsrv && \ + mkdir -p /var/log/ps3netsrv && \ + chown -R nobody:nogroup /var/log/ps3netsrv && \ + echo "Removing not needed packages" && \ + apk del --purge \ + xz && \ + echo "Cleaning up temp directory..." && \ + rm -rf /tmp/* + +# Add files +COPY rootfs/ / + +ENV PS3NETSRV_BINARY=mbedtls \ + PS3NETSRV_PORT=38008 \ + PS3NETSRV_WHITELIST= + +# Define mountable directories +VOLUME ["/games"] + +# Expose ports +EXPOSE 38008 + +# Start s6 +ENTRYPOINT ["/init"] diff --git a/rootfs/etc/cont-init.d/00-adduser b/rootfs/etc/cont-init.d/00-adduser deleted file mode 100644 index 79275cc5..00000000 --- a/rootfs/etc/cont-init.d/00-adduser +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/with-contenv bash - -USER_ID=${USER_ID:-1000} -GROUP_ID=${GROUP_ID:-1000} - -groupmod -o -g "$GROUP_ID" ps3netsrv -usermod -o -u "$USER_ID" ps3netsrv - -echo ' -------------------------------------- -GID/UID --------------------------------------' -echo " -User uid: $(id -u ps3netsrv) -User gid: $(id -g ps3netsrv) -------------------------------------- -" diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/dependencies.d/base b/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/dependencies.d/base new file mode 100644 index 00000000..e69de29b diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/run b/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/run new file mode 100755 index 00000000..84ae945d --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/run @@ -0,0 +1,23 @@ +#!/command/with-contenv bash + +if [[ -n "${USER_ID}" ]] && [[ -n "${GROUP_ID}" ]]; then + USER_ID="${USER_ID}" + GROUP_ID="${GROUP_ID}" + echo "USER_ID and GROUP_ID are deprecated, please use PUID and PGID instead!" +elif [[ -n "${PUID}" ]] && [[ -n "${PGID}" ]]; then + USER_ID="${PUID}" + GROUP_ID="${PGID}" +fi + +groupmod -o -g "${GROUP_ID:-1000}" ps3netsrv +usermod -o -u "${USER_ID:-1000}" ps3netsrv + +echo ' +------------------------------------- +GID/UID +-------------------------------------' +echo " +ps3netsrv uid: $(id -u ps3netsrv) +ps3netsrv gid: $(id -g ps3netsrv) +------------------------------------- +" diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/type b/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/type new file mode 100644 index 00000000..3d92b15f --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/up b/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/up new file mode 100644 index 00000000..53c63386 --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/init-adduser/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-adduser/run \ No newline at end of file diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/dependencies.d/init-adduser b/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/dependencies.d/init-adduser new file mode 100644 index 00000000..e69de29b diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/run b/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/run new file mode 100755 index 00000000..ff49e771 --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/run @@ -0,0 +1,100 @@ +#!/command/with-contenv bash + +if [[ "${PS3NETSRV_SKIP_CHECKS:-}" == "true" ]]; then + echo "Skipping folder structure checks because PS3NETSRV_SKIP_CHECKS is true..." + exit 0 +fi + +echo ' +------------------------------------- +Checking folder structure of /games directory +-------------------------------------' + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' + +declare -a folders=("GAMES" "PS3ISO" "PSXISO" "PS2ISO" "PSPISO" "BDISO" "DVDISO" "ROMS" "GAMEI" "PKG" "MOVIES" "MUSIC" "PICTURE" "REDKEY") +declare -a existing_folders=() + +function check_permissions() { + local fullpath="${1:-}" + if ! s6-setuidgid ps3netsrv test -r "${fullpath}"; then + echo -e "${RED}ERROR: ${fullpath} is not readable for user ps3netsrv! Check ownership and permissions!${NC}" + echo -e "${fullpath} is owned by $(stat -c '%U' "${fullpath}") and has permissions $(stat -c '%A' "${fullpath}")" + ls -l "${fullpath}" + else + echo -e "${GREEN}OK: ${fullpath} is readable${NC}" + if [[ -z "$(ls "${fullpath}")" ]]; then + echo -e "${YELLOW}WARNING: ${fullpath} is empty, make sure to put your games here!${NC}" + else + unreadable_files="$(find "${fullpath}" -not -user "$(id -u ps3netsrv)" -not -exec s6-setuidgid ps3netsrv test -r {} \; -print)" + unreadable_files+="\n$(find "${fullpath}" -not -group "$(id -g ps3netsrv)" -not -exec s6-setuidgid ps3netsrv test -r {} \; -print)" + # remove duplicates from unreadable_files + unreadable_files="$(echo -e "${unreadable_files}" | sort | uniq)" + if [[ -n "${unreadable_files}" ]]; then + echo -e "${RED}ERROR: Found files or directories in ${fullpath} that ps3netsrv does not have permission to read:${NC}" + # loop over files line by line and ls -la the file: + while IFS= read -r file; do + ls -l "${file}" + done <<<"${unreadable_files}" + fi + fi + existing_folders+=("${fullpath}") + fi +} + +for folder in "${folders[@]}"; do + echo "--- Checking ${folder} ---" + if [[ -d "/games/${folder}" ]]; then + echo "Directory /games/${folder}/ found, checking permissions..." + check_permissions "/games/${folder}" + fi + + if [[ -f "/games/${folder}.INI" ]]; then + echo -e "File /games/${folder}.INI found, checking if linked directories inside exist..." + mapfile -t ini_folders <"/games/${folder}.INI" + for linked_dir in "${ini_folders[@]}"; do + echo "--- Checking ${folder}.INI -> ${linked_dir} ---" + if [[ -d "${linked_dir}" ]]; then + echo "Linked directory ${linked_dir} found in ${folder}.INI, checking permissions..." + check_permissions "${linked_dir}" + else + echo -e "${RED}ERROR: Linked directory ${linked_dir} not found, please check your ${folder}.INI...${NC}" + fi + done + fi + + if [[ ! -d "/games/${folder}" ]] && [[ ! -f "/games/${folder}.INI" ]]; then + echo -e "Directory /games/${folder}/ and /games/${folder}.INI do not exist, skipping checks..." + fi +done + +if [[ "${#existing_folders[@]}" -eq 0 ]]; then + echo -e "${RED}You do not have any readable folders in /games!${NC}\nPlease read the wiki https://github.com/aldostools/webMAN-MOD/wiki/~-PS3-NET-Server" + exit 0 +fi + +if [[ "${PS3NETSRV_FIX_PERMISSIONS:-false}" == "true" ]]; then + echo >&2 "WARNING: PS3NETSRV_FIX_PERMISSIONS is enabled! This will change the ownership and permissions of all folders in /games!" + echo "Changing ownership of /games to ps3netsrv:ps3netsrv ..." + chown ps3netsrv:ps3netsrv /games + echo "Changing permissions of /games to ${PS3NETSRV_FOLDER_PERMISSIONS:-755}..." + chmod "${PS3NETSRV_FOLDER_PERMISSIONS:-755}" /games + for folder in "${existing_folders[@]}"; do + echo "Changing ownership of files and directories in ${folder} to ps3netsrv:ps3netsrv..." + find "${folder}" -not -user "$(id -u ps3netsrv)" -exec chown -h ps3netsrv {} \; + find "${folder}" -not -group "$(id -g ps3netsrv)" -exec chgrp -h ps3netsrv {} \; + + echo "Changing permissions of directories in ${folder} to ${PS3NETSRV_FOLDER_PERMISSIONS:-755}..." + find "${folder}" -type d -exec chmod "${PS3NETSRV_FOLDER_PERMISSIONS:-755}" {} \; + + echo "Changing permissions of files in ${folder} to ${PS3NETSRV_FILE_PERMISSIONS:-644}..." + find "${folder}" -type f -exec chmod "${PS3NETSRV_FILE_PERMISSIONS:-644}" {} \; + done +fi + +echo " +------------------------------------- +" diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/type b/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/type new file mode 100644 index 00000000..3d92b15f --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/up b/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/up new file mode 100644 index 00000000..6622c17a --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/init-check-folders/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-check-folders/run \ No newline at end of file diff --git a/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/dependencies.d/init-check-folders b/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/dependencies.d/init-check-folders new file mode 100644 index 00000000..e69de29b diff --git a/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/run b/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/run new file mode 100755 index 00000000..b6db4206 --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/run @@ -0,0 +1,17 @@ +#!/command/with-contenv bash + +cd /games || exit 1 + +UMASK=${UMASK:-022} +umask "$UMASK" + +if ! [[ "${PS3NETSRV_BINARY}" =~ ^(mbedtls|polarssl)$ ]]; then + echo "Invalid binary specified \"${PS3NETSRV_BINARY}\", defaulting to mbedtls..." + PS3NETSRV_BINARY="mbedtls" +fi + +echo "Using binary: ${PS3NETSRV_BINARY}" +echo "Using port: ${PS3NETSRV_PORT}" +echo "Using whitelist: ${PS3NETSRV_WHITELIST}" + +s6-setuidgid ps3netsrv "/usr/bin/ps3netsrv-${PS3NETSRV_BINARY}" /games "${PS3NETSRV_PORT}" ${PS3NETSRV_WHITELIST} diff --git a/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/type b/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/type new file mode 100644 index 00000000..1780f9f4 --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/svc-ps3netsrv/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-adduser b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-adduser new file mode 100644 index 00000000..e69de29b diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-check-folders b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-check-folders new file mode 100644 index 00000000..e69de29b diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/svc-ps3netsrv b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/svc-ps3netsrv new file mode 100644 index 00000000..e69de29b diff --git a/rootfs/etc/services.d/ps3netsrv/log/run b/rootfs/etc/services.d/ps3netsrv/log/run deleted file mode 100755 index 37b47aa4..00000000 --- a/rootfs/etc/services.d/ps3netsrv/log/run +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/execlineb -s6-envuidgid nobody -s6-applyuidgid -U -s6-log -bp T 1 n20 s1000000 T /var/log/ps3netsrv \ No newline at end of file diff --git a/rootfs/etc/services.d/ps3netsrv/run b/rootfs/etc/services.d/ps3netsrv/run deleted file mode 100755 index d90cae7f..00000000 --- a/rootfs/etc/services.d/ps3netsrv/run +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/with-contenv bash - -cd /games - -UMASK=${UMASK:-022} -umask "$UMASK" - -echo "Using port: ${PS3NETSRV_PORT}" -echo "Using whitelist: ${PS3NETSRV_WHITELIST}" - -s6-setuidgid ps3netsrv /usr/local/bin/ps3netsrv /games "${PS3NETSRV_PORT}" ${PS3NETSRV_WHITELIST} diff --git a/slim.Dockerfile b/slim.Dockerfile new file mode 100644 index 00000000..f62af293 --- /dev/null +++ b/slim.Dockerfile @@ -0,0 +1,164 @@ +# +# ps3netsrv Dockerfile +# +# https://github.com/shawly/docker-ps3netsrv +# + +# Set debian version +ARG DEBIAN_VERSION=bookworm-slim + +# Set vars for s6 overlay +ARG S6_OVERLAY_RELEASE=v3.2.0.2 +ARG S6_OVERLAY_ARCH=x86_64 +ARG S6_OVERLAY_DOWNLOAD_URL=https://github.com/just-containers/s6-overlay/releases/download + +# Set PS3NETSRV vars +ARG PS3NETSRV_REPO=https://github.com/aldostools/webMAN-MOD.git +ARG PS3NETSRV_SRC_DIR=_Projects_/ps3netsrv +ARG PS3NETSRV_SRC_REF=master +ARG BUILD_FROM_GIT=true + +ARG PS3NETSRV_VERSION +ARG PS3NETSRV_GITHUB_API_URL=https://api.github.com/repos/aldostools/webMAN-MOD/releases + +# Set base images with s6 overlay download variable (necessary for multi-arch building via GitHub workflows) +FROM debian:${DEBIAN_VERSION} AS debian-amd64 + +ARG S6_OVERLAY_ARCH=x86_64 + +FROM debian:${DEBIAN_VERSION} AS debian-armv6 + +ARG S6_OVERLAY_ARCH=armhf + +FROM debian:${DEBIAN_VERSION} AS debian-armv7 + +ARG S6_OVERLAY_ARCH=arm + +FROM debian:${DEBIAN_VERSION} AS debian-arm64 + +ARG S6_OVERLAY_ARCH=aarch64 + +# Build ps3netsrv:master +FROM debian:${DEBIAN_VERSION} AS builder + +ARG PS3NETSRV_REPO +ARG PS3NETSRV_SRC_DIR +ARG PS3NETSRV_SRC_REF +ARG PS3NETSRV_GITHUB_API_URL +ARG PS3NETSRV_VERSION +ARG BUILD_FROM_GIT +ARG DEBIAN_FRONTEND=noninteractive + +# Change working dir +WORKDIR /tmp + +# Install deps and build binary +RUN \ + set -e && \ + echo "Installing build dependencies..." && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + curl \ + git \ + libmbedtls-dev \ + libssl-dev \ + meson \ + ninja-build \ + unzip \ + xz-utils + +RUN \ + bash -c "[ "${BUILD_FROM_GIT:-}" != "true" ]" || (echo "Building ps3netsrv from git repo (ref: ${PS3NETSRV_SRC_REF:?})..." && \ + mkdir -p /tmp/repo/ && \ + cd /tmp/repo/ && \ + git init && \ + git remote add origin "${PS3NETSRV_REPO:?}" && \ + git fetch --depth 1 origin "${PS3NETSRV_SRC_REF:?}" && \ + git checkout FETCH_HEAD && \ + cd /tmp/repo/${PS3NETSRV_SRC_DIR:?} && \ + meson build --buildtype=release && \ + ninja -C build/ && \ + mkdir -p /tmp/ps3netsrv-bin && \ + cp -v /tmp/repo/${PS3NETSRV_SRC_DIR:?}/build/ps3netsrv /tmp/ps3netsrv-bin/ps3netsrv-mbedtls && \ + make -f Makefile.linux && \ + cp -v ps3netsrv /tmp/ps3netsrv-bin/ps3netsrv-polarssl) + +RUN \ + bash -c "[ "${BUILD_FROM_GIT:-false}" == "true" ]" || (echo "Building ps3netsrv from release (ps3netsrv_${PS3NETSRV_VERSION:-}.zip)..." && \ + cd /tmp && \ + echo "Getting releases from ${PS3NETSRV_GITHUB_API_URL:?}" && \ + curl -sL -o releases.json "${PS3NETSRV_GITHUB_API_URL:?}" && \ + PS3NETSRV_URL="$(jq -r --arg version "${PS3NETSRV_VERSION:?}" '[.[].assets[] | select(.name | startswith("ps3netsrv_" + $version)) | .browser_download_url] | first' releases.json)" && \ + echo "Downloading release from ${PS3NETSRV_URL:?}" && \ + curl -sL --output /tmp/ps3netsrv.zip "${PS3NETSRV_URL:?}" && \ + echo "Extracting release..." && \ + unzip /tmp/ps3netsrv.zip -d /tmp && \ + find "/tmp" -type d -maxdepth 1 -iname "*ps3netsrv_*" -exec mv -f {} "/tmp/ps3netsrv" \; && \ + cd /tmp/ps3netsrv/ps3netsrv && \ + echo "Building release..." && \ + meson build --buildtype=release && \ + ninja -C build/ && \ + mkdir -p /tmp/ps3netsrv-bin && \ + cp -v build/ps3netsrv /tmp/ps3netsrv-bin/ && \ + echo "Building alternative with POLARSSL instead of mbedTLS..." && \ + make -f Makefile.linux && \ + mkdir -p /tmp/ps3netsrv-bin && \ + cp -v ./ps3netsrv /tmp/ps3netsrv-bin/ps3netsrv-polarssl) + +# Runtime container +FROM debian-${TARGETARCH:-amd64}${TARGETVARIANT} + +ARG S6_OVERLAY_RELEASE +ARG S6_OVERLAY_ARCH +ARG S6_OVERLAY_DOWNLOAD_URL +ARG DEBIAN_FRONTEND=noninteractive + +# Add s6-overlay files +ADD ${S6_OVERLAY_DOWNLOAD_URL}/${S6_OVERLAY_RELEASE}/s6-overlay-noarch.tar.xz /tmp +ADD ${S6_OVERLAY_DOWNLOAD_URL}/${S6_OVERLAY_RELEASE}/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz /tmp + +# Copy binary from build container +COPY --from=builder /tmp/ps3netsrv-bin/ps3netsrv* /usr/bin/ + +# Install runtime deps and add users +RUN \ + set -e && \ + echo "Installing runtime dependencies..." && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + libmbedtls14 \ + tzdata \ + xz-utils && \ + echo "Extracting s6 overlay..." && \ + tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz && \ + tar -C / -Jxpf /tmp/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz && \ + echo "Creating ps3netsrv user..." && \ + useradd -u 1000 -U -M -s /bin/false ps3netsrv && \ + usermod -G users ps3netsrv && \ + mkdir -p /var/log/ps3netsrv && \ + chown -R nobody:nogroup /var/log/ps3netsrv && \ + echo "Removing not needed packages" && \ + apt-get autoremove -y \ + xz-utils && \ + echo "Cleaning up temp directory..." && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* + +# Add files +COPY rootfs/ / + +ENV PS3NETSRV_BINARY=mbedtls \ + PS3NETSRV_PORT=38008 \ + PS3NETSRV_WHITELIST= + +# Define mountable directories +VOLUME ["/games"] + +# Expose ports +EXPOSE 38008 + +# Start s6 +ENTRYPOINT ["/init"] diff --git a/tests/setup-test-structure.sh b/tests/setup-test-structure.sh new file mode 100644 index 00000000..29a0adfd --- /dev/null +++ b/tests/setup-test-structure.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +# run this script as root +if [ "$EUID" -ne 0 ]; then + echo "Please run as root" + exit +fi + +if [ ! -d "tests/" ]; then + echo "Please run this script from the root of the project" + exit +fi + +function cleanup { + rm -rf tests/games +} + +function create_dummy_file { + local dir="tests/games/$1" + local filename=$2 + local ext=$3 + local owner=$4 + local group=$5 + local path="${dir}/${filename}.${ext}" + echo "Creating dummy file: ${path}" + mkdir -p "${dir}" + touch "${path}" + chown -v "$owner:$group" "${path}" +} + +function create_dummy_ps3game { + local dir="tests/games/$1" + local foldername=$2 + local owner=$3 + local group=$4 + local path="${dir}/${foldername}" + echo "Creating dummy game folder: ${path}" + mkdir -p "${path}/PS3_GAME" + touch "${path}/PS3_DISC.SFB" + touch "${path}/PS3_GAME/PARAM.SFO" + chown -Rv "$owner:$group" "${path}" +} + +function create_linked_ini { + local dir="tests/games/$1" + local owner=$2 + local group=$3 + local path="${dir}.INI" + echo "Creating linked ini file: ${path}" + # Read content from stdin and write to the .ini file + cat > "${path}" + chown "$owner:$group" "${path}" +} + +cleanup + +mkdir -p tests/games/PS3ISO \ + tests/games/PS2ISO \ + tests/games/PKG \ + tests/games/PSXISO \ + tests/games/snes \ + tests/games/gba + +chown -Rv 1000:1000 tests/games/PS3ISO + +create_dummy_file "PS3ISO" "dummy_the_game" "iso" "root" "root" +chmod 0600 tests/games/PS3ISO/dummy_the_game.iso + +create_dummy_file "PS3ISO" "dummy_the_game_3" "iso" "1000" "nogroup" + +create_dummy_ps3game "GAMES" "DUMMY_THE_GAME" "nobody" "nogroup" +chown -Rv 1000:nogroup tests/games/GAMES/DUMMY_THE_GAME/PS3_GAME + +create_dummy_ps3game "GAMES" "DUMMY_THE_GAME_2" "nobody" "nogroup" +chown -Rv nobody:nogroup tests/games/GAMES/DUMMY_THE_GAME/PS3_GAME + +create_dummy_file "PS2ISO" "dummy_the_prequel" "iso" "nobody" "1000" + +create_dummy_file "PKG" "dummy_the_dlc" "pkg" "nobody" "nogroup" + +create_dummy_file "PSXISO" "dummy_the_original" "cue" "1000" "nogroup" +create_dummy_file "PSXISO" "dummy_the_original" "bin" "1000" "nogroup" + +create_dummy_file "snes" "rom" "sfc" "nobody" "nogroup" +create_dummy_file "gba" "rom" "gba" "1000" "1000" +create_dummy_file "gba" "rom2" "gba" "root" "root" +chmod 600 tests/games/gba/rom2.gba + +mkdir -p tests/games/unreadable +chmod 700 tests/games/unreadable +chown root:root tests/games/unreadable + +create_linked_ini "ROMS" "nobody" "nogroup" <