diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml index b14e935..74c3225 100644 --- a/.github/workflows/containers.yml +++ b/.github/workflows/containers.yml @@ -3,10 +3,9 @@ run-name: ${{ inputs.ref }} ${{ inputs.target }} env: FILE_HOST: https://mirror-03.infra.openwrt.org - DOCKER_USER: ${{ secrets.DOCKER_USER }} - DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} - QUAY_USER: ${{ secrets.QUAY_USER }} - QUAY_TOKEN: ${{ secrets.QUAY_TOKEN }} + # The login user is not the image namespace, e.g. Quay.io robot accounts + DOCKER_NAMESPACE: ${{ secrets.DOCKER_USER != '' && secrets.DOCKER_TOKEN != '' && (vars.DOCKER_NAMESPACE || github.repository_owner) || '' }} + QUAY_NAMESPACE: ${{ secrets.QUAY_USER != '' && secrets.QUAY_TOKEN != '' && (vars.QUAY_NAMESPACE || github.repository_owner) || '' }} on: # push: @@ -31,6 +30,8 @@ on: description: "Prefix for the image name (add '-' at the end)" required: false +permissions: {} + jobs: dispatch-scheduled-rebuilds: name: Dispatch scheduled rebuilds @@ -51,6 +52,8 @@ jobs: name: Set matrix runs-on: ubuntu-latest if: github.event_name != 'schedule' + permissions: + contents: read outputs: imagebuilders: ${{ steps.find_targets.outputs.imagebuilders }} @@ -182,6 +185,9 @@ jobs: name: ImageBuilder runs-on: ubuntu-latest needs: generate_matrix + permissions: + contents: read + packages: write strategy: fail-fast: False matrix: ${{fromJson(needs.generate_matrix.outputs.imagebuilders)}} @@ -196,14 +202,14 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker.io Container Registry - if: github.event_name != 'pull_request' && env.DOCKER_USER != '' && env.DOCKER_TOKEN != '' + if: github.event_name != 'pull_request' && env.DOCKER_NAMESPACE != '' uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to Quay.io Container Registry - if: github.event_name != 'pull_request' && env.QUAY_USER != '' && env.QUAY_TOKEN != '' + if: github.event_name != 'pull_request' && env.QUAY_NAMESPACE != '' uses: docker/login-action@v4 with: registry: quay.io @@ -216,8 +222,8 @@ jobs: with: images: | ghcr.io/${{ github.repository_owner }}/imagebuilder - ${{ env.DOCKER_USER != '' && format('docker.io/{0}/imagebuilder', env.DOCKER_USER) || '' }} - ${{ env.QUAY_USER != '' && format('quay.io/{0}/imagebuilder', env.QUAY_USER) || '' }} + ${{ env.DOCKER_NAMESPACE != '' && format('docker.io/{0}/imagebuilder', env.DOCKER_NAMESPACE) || '' }} + ${{ env.QUAY_NAMESPACE != '' && format('quay.io/{0}/imagebuilder', env.QUAY_NAMESPACE) || '' }} flavor: | latest=false prefix=${{ github.event.inputs.prefix }} @@ -254,18 +260,14 @@ jobs: - name: Push if: github.event_name != 'pull_request' - uses: docker/build-push-action@v7 - with: - push: true - no-cache: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: | - DOWNLOAD_FILE=imagebuilder-.*x86_64.tar.[xz|zst] - VERSION_PATH=${{ needs.generate_matrix.outputs.version_path }} - TARGET=${{ matrix.target }} - FILE_HOST=${{ needs.generate_matrix.outputs.file_host }} - RUN_SETUP=${{ needs.generate_matrix.outputs.run_setup }} + env: + IMAGE_ID: ${{ steps.build.outputs.imageid }} + TAGS: ${{ steps.meta.outputs.tags }} + run: | + for tag in $TAGS; do + docker tag "$IMAGE_ID" "$tag" + docker push "$tag" + done - name: Cleanup Docker containers run: docker system prune -f @@ -274,6 +276,9 @@ jobs: name: SDK runs-on: ubuntu-latest needs: generate_matrix + permissions: + contents: read + packages: write strategy: fail-fast: False matrix: ${{fromJson(needs.generate_matrix.outputs.sdks)}} @@ -288,14 +293,14 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker.io Container Registry - if: github.event_name != 'pull_request' && env.DOCKER_USER != '' && env.DOCKER_TOKEN != '' + if: github.event_name != 'pull_request' && env.DOCKER_NAMESPACE != '' uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to Quay.io Container Registry - if: github.event_name != 'pull_request' && env.QUAY_USER != '' && env.QUAY_TOKEN != '' + if: github.event_name != 'pull_request' && env.QUAY_NAMESPACE != '' uses: docker/login-action@v4 with: registry: quay.io @@ -308,8 +313,8 @@ jobs: with: images: | ghcr.io/${{ github.repository_owner }}/sdk - ${{ env.DOCKER_USER != '' && format('docker.io/{0}/sdk', env.DOCKER_USER) || '' }} - ${{ env.QUAY_USER != '' && format('quay.io/{0}/sdk', env.QUAY_USER) || '' }} + ${{ env.DOCKER_NAMESPACE != '' && format('docker.io/{0}/sdk', env.DOCKER_NAMESPACE) || '' }} + ${{ env.QUAY_NAMESPACE != '' && format('quay.io/{0}/sdk', env.QUAY_NAMESPACE) || '' }} flavor: | latest=false prefix=${{ github.event.inputs.prefix }} @@ -322,8 +327,8 @@ jobs: with: images: | ghcr.io/${{ github.repository_owner }}/sdk - ${{ env.DOCKER_USER != '' && format('docker.io/{0}/sdk', env.DOCKER_USER) || '' }} - ${{ env.QUAY_USER != '' && format('quay.io/{0}/sdk', env.QUAY_USER) || '' }} + ${{ env.DOCKER_NAMESPACE != '' && format('docker.io/{0}/sdk', env.DOCKER_NAMESPACE) || '' }} + ${{ env.QUAY_NAMESPACE != '' && format('quay.io/{0}/sdk', env.QUAY_NAMESPACE) || '' }} flavor: | latest=false prefix=${{ github.event.inputs.prefix }} @@ -337,8 +342,8 @@ jobs: with: images: | ghcr.io/${{ github.repository_owner }}/sdk - ${{ env.DOCKER_USER != '' && format('docker.io/{0}/sdk', env.DOCKER_USER) || '' }} - ${{ env.QUAY_USER != '' && format('quay.io/{0}/sdk', env.QUAY_USER) || '' }} + ${{ env.DOCKER_NAMESPACE != '' && format('docker.io/{0}/sdk', env.DOCKER_NAMESPACE) || '' }} + ${{ env.QUAY_NAMESPACE != '' && format('quay.io/{0}/sdk', env.QUAY_NAMESPACE) || '' }} flavor: | latest=false prefix=${{ github.event.inputs.prefix }} @@ -352,8 +357,8 @@ jobs: with: images: | ghcr.io/${{ github.repository_owner }}/sdk - ${{ env.DOCKER_USER != '' && format('docker.io/{0}/sdk', env.DOCKER_USER) || '' }} - ${{ env.QUAY_USER != '' && format('quay.io/{0}/sdk', env.QUAY_USER) || '' }} + ${{ env.DOCKER_NAMESPACE != '' && format('docker.io/{0}/sdk', env.DOCKER_NAMESPACE) || '' }} + ${{ env.QUAY_NAMESPACE != '' && format('quay.io/{0}/sdk', env.QUAY_NAMESPACE) || '' }} flavor: | latest=false prefix=${{ github.event.inputs.prefix }} @@ -366,8 +371,8 @@ jobs: with: images: | ghcr.io/${{ github.repository_owner }}/sdk - ${{ env.DOCKER_USER != '' && format('docker.io/{0}/sdk', env.DOCKER_USER) || '' }} - ${{ env.QUAY_USER != '' && format('quay.io/{0}/sdk', env.QUAY_USER) || '' }} + ${{ env.DOCKER_NAMESPACE != '' && format('docker.io/{0}/sdk', env.DOCKER_NAMESPACE) || '' }} + ${{ env.QUAY_NAMESPACE != '' && format('quay.io/{0}/sdk', env.QUAY_NAMESPACE) || '' }} tags: latest - name: Build @@ -406,23 +411,19 @@ jobs: - name: Push if: github.event_name != 'pull_request' - uses: docker/build-push-action@v7 - with: - push: true - no-cache: true - tags: | + env: + IMAGE_ID: ${{ steps.build.outputs.imageid }} + TAGS: | ${{ steps.meta_ref.outputs.tags }} ${{ steps.meta_version.outputs.tags }} ${{ steps.meta_master.outputs.tags }} ${{ steps.meta_target_arch.outputs.tags }} ${{ steps.meta_latest.outputs.tags }} - build-args: | - DOWNLOAD_FILE=sdk-.*.Linux-x86_64.tar.[xz|zst] - VERSION_PATH=${{ needs.generate_matrix.outputs.version_path }} - TARGET=${{ matrix.target }} - FILE_HOST=${{ needs.generate_matrix.outputs.file_host }} - RUN_SETUP=${{ needs.generate_matrix.outputs.run_setup }} - labels: ${{ steps.meta_ref.outputs.labels }} + run: | + for tag in $TAGS; do + docker tag "$IMAGE_ID" "$tag" + docker push "$tag" + done - name: Cleanup Docker containers run: docker system prune -f @@ -431,6 +432,9 @@ jobs: name: RootFS runs-on: ubuntu-latest needs: generate_matrix + permissions: + contents: read + packages: write if: needs.generate_matrix.outputs.rootfs != '{"include":[]}' strategy: fail-fast: False @@ -455,14 +459,14 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker.io Container Registry - if: github.event_name != 'pull_request' && env.DOCKER_USER != '' && env.DOCKER_TOKEN != '' + if: github.event_name != 'pull_request' && env.DOCKER_NAMESPACE != '' uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to Quay.io Container Registry - if: github.event_name != 'pull_request' && env.QUAY_USER != '' && env.QUAY_TOKEN != '' + if: github.event_name != 'pull_request' && env.QUAY_NAMESPACE != '' uses: docker/login-action@v4 with: registry: quay.io @@ -475,8 +479,8 @@ jobs: with: images: | ghcr.io/${{ github.repository_owner }}/rootfs - ${{ env.DOCKER_USER != '' && format('docker.io/{0}/rootfs', env.DOCKER_USER) || '' }} - ${{ env.QUAY_USER != '' && format('quay.io/{0}/rootfs', env.QUAY_USER) || '' }} + ${{ env.DOCKER_NAMESPACE != '' && format('docker.io/{0}/rootfs', env.DOCKER_NAMESPACE) || '' }} + ${{ env.QUAY_NAMESPACE != '' && format('quay.io/{0}/rootfs', env.QUAY_NAMESPACE) || '' }} flavor: | latest=false prefix=${{ github.event.inputs.prefix }} @@ -525,15 +529,14 @@ jobs: - name: Push if: github.event_name != 'pull_request' - uses: docker/build-push-action@v7 - with: - no-cache: true - push: true - tags: ${{ steps.meta.outputs.tags }} - file: Dockerfile.rootfs - build-args: ${{ steps.build_args.outputs.args }} - labels: ${{ steps.meta.outputs.labels }} - platforms: linux/${{ matrix.arch }} + env: + IMAGE_ID: ${{ steps.build.outputs.imageid }} + TAGS: ${{ steps.meta.outputs.tags }} + run: | + for tag in $TAGS; do + docker tag "$IMAGE_ID" "$tag" + docker push "$tag" + done - name: Cleanup Docker containers run: docker system prune -f diff --git a/README.md b/README.md index 581699e..9fc92cd 100644 --- a/README.md +++ b/README.md @@ -180,22 +180,14 @@ access. Once closed the container is removed. ## GitHub Actions CI & Registries -The GitHub Actions workflow `.github/workflows/containers.yml` automatically builds and pushes the containers to the registries. If you fork this repository, you can also push to your own registry accounts. +The GitHub Actions workflow `.github/workflows/containers.yml` builds the containers and pushes them to `//`, so forks push to their own namespace. -### GitHub Container Registry (GHCR) -By default, the workflow will push containers to `ghcr.io/${{ github.repository_owner }}/`. This works automatically out of the box using GitHub's built-in `GITHUB_TOKEN` and does not require any additional setup. +Pushing to ghcr.io works out of the box using GitHub's built-in `GITHUB_TOKEN`. To also push to Docker Hub or Quay.io, configure the following secrets under your repository's **Settings -> Secrets and variables -> Actions**. A registry without both its user and token is skipped. -### Docker Hub & Quay.io -To push to your own Docker Hub or Quay.io registries, you need to configure the following secrets under your repository's **Settings -> Secrets and variables -> Actions**: +* `DOCKER_USER` and `DOCKER_TOKEN` - the Docker Hub user and its Personal Access Token. +* `QUAY_USER` and `QUAY_TOKEN` - the Quay.io user or robot account (`org+name`) and its token. A robot account needs write permission on the existing `sdk`, `imagebuilder` and `rootfs` repositories. -* **Docker Hub (docker.io)**: - * `DOCKER_USER` - Your Docker Hub username. - * `DOCKER_TOKEN` - Your Docker Hub Personal Access Token. -* **Quay.io (quay.io)**: - * `QUAY_USER` - Your Quay.io username. - * `QUAY_TOKEN` - Your Quay.io OAuth Token / Password. - -If these secrets are not configured, the workflow will automatically skip logging in and pushing to these registries without failing the build. +To push to a different namespace than the repository owner, set the `DOCKER_NAMESPACE` or `QUAY_NAMESPACE` variable. The login user needs push access to it. ## Build Your Own