diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b767cda..5371df4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -20,15 +20,3 @@ updates: # prefix all commit messages with "chore(deps): " commit-message: prefix: "chore(deps): " - - # Create a group of dependencies to be updated together in one pull request - groups: - # Update all dependencies from redhat-actions together - redhat-actions: - patterns: - - "redhat-actions/*" - - # Update all non-specified dependencies together - all: - patterns: - - "*" diff --git a/.github/workflows/container-build.yml b/.github/workflows/container-build.yml index 680f197..892ec5d 100644 --- a/.github/workflows/container-build.yml +++ b/.github/workflows/container-build.yml @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -name: 'Build and push anki-sync container' +name: 'Build and push container' # run workflow on every branch, only upload on main (allow manual trigger) on: [push, pull_request, workflow_dispatch] @@ -14,6 +14,12 @@ jobs: # use ubuntu as runner runs-on: ubuntu-latest + + strategy: + matrix: + # build for every application + app: + - anki-sync-server permissions: packages: write @@ -26,11 +32,15 @@ jobs: - name: Setup yq uses: mikefarah/yq@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Setup oras + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' uses: oras-project/setup-oras@v1 - name: Login to GitHub Container Registry - uses: redhat-actions/podman-login@v1 + uses: docker/login-action@v3 if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' with: registry: ghcr.io @@ -38,10 +48,9 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Login to DockerHub - uses: redhat-actions/podman-login@v1 + uses: docker/login-action@v3 if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' with: - registry: docker.io username: federdaemn password: ${{ secrets.DOCKER_TOKEN }} @@ -49,7 +58,7 @@ jobs: id: set-op run: | # extract version from ./values.yml - echo "anki-version=$(yq '.version.anki-version' ./values.yml)" \ + echo "software-version=$(yq '.version.software-version' ./${{ matrix.app }}/values.yml)" \ >> $GITHUB_OUTPUT # get current date+time @@ -58,59 +67,92 @@ jobs: # get current date+time docker tag compatible echo "time-docker=$(date --utc +'%Y-%m-%dt%H-%M-%Sz')" >> $GITHUB_OUTPUT - - name: Build image - id: build_image - uses: redhat-actions/buildah-build@v2 + - name: Build and push image in production + uses: docker/build-push-action@v5 + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' with: + # directly push image + push: true + + # use local repository + context: . + # which containerfile to build from - containerfiles: | - ./containerfile + file: | + ./${{ matrix.app }}/containerfile - # set labels to append to the image + # build args to pass to the build + build-args: | + software_version=${{ steps.set-op.outputs.software-version }} + + # build for many platforms at the same time + platforms: | + linux/amd64 + linux/arm64 + linux/arm/v7 + linux/arm/v6 + + # set general labels to append to all images labels: | # opencontainer labels specified # https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys - org.opencontainers.image.title=oci-anki-sync - org.opencontainers.image.description=Anki sync server (anki-sync-server) in a container - org.opencontainers.image.authors=Frederik Zorn + org.opencontainers.image.title="${{ matrix.app }}" + org.opencontainers.image.authors=Frederik Zorn org.opencontainers.image.created=${{ steps.set-op.outputs.time }} - org.opencontainers.image.version=${{ steps.set-op.outputs.anki-version }} - org.opencontainers.image.licenses=AGPL-3.0-or-later - org.opencontainers.image.url=https://github.com/federdaemn/oci-anki-sync - org.opencontainers.image.source=https://github.com/federdaemn/oci-anki-sync + org.opencontainers.image.version=${{ steps.set-op.outputs.software-version }} + org.opencontainers.image.source=https://github.com/federdaemn/container # artfifacthub labels specified # https://artifacthub.io/docs/topics/repositories/container-images/#image-metadata - io.artifacthub.package.readme-url=https://raw.githubusercontent.com/federdaemn/oci-anki-sync/main/README.md + io.artifacthub.package.readme-url=https://raw.githubusercontent.com/federdaemn/container/main/${{ matrix.app }}/README.md io.artifacthub.package.maintainers=[{"name":"federdaemn","email":"federdaemn@mail.de"}] - io.artifacthub.package.keywords=anki,sync,server,anki-sync-server,anki-sync - io.artifacthub.package.logo-url=https://raw.githubusercontent.com/federdaemn/oci-anki-sync/main/imgs/anki/logo.png - io.artifacthub.package.alternative-locations=docker.io/federdaemn/oci-anki-sync - - # build args to pass to the build - build-args: | - anki_version=${{ steps.set-op.outputs.anki-version }} + io.artifacthub.package.logo-url=https://raw.githubusercontent.com/federdaemn/container/main/${{ matrix.app }}/imgs/ah-logo.png + io.artifacthub.package.alternative-locations=docker.io/federdaemn/${{ matrix.app }} # tags to build the image with tags: | - ghcr.io/federdaemn/oci-anki-sync:latest - ghcr.io/federdaemn/oci-anki-sync:${{ steps.set-op.outputs.anki-version }} - ghcr.io/federdaemn/oci-anki-sync:${{ steps.set-op.outputs.time-docker }} - docker.io/federdaemn/oci-anki-sync:latest - docker.io/federdaemn/oci-anki-sync:${{ steps.set-op.outputs.anki-version }} - docker.io/federdaemn/oci-anki-sync:${{ steps.set-op.outputs.time-docker }} - - - name: Push image - uses: redhat-actions/push-to-registry@v2 - if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' - with: - tags: ${{ steps.build_image.outputs.tags }} + ghcr.io/federdaemn/${{ matrix.app }}:latest + ghcr.io/federdaemn/${{ matrix.app }}:${{ steps.set-op.outputs.software-version }} + ghcr.io/federdaemn/${{ matrix.app }}:${{ steps.set-op.outputs.time-docker }} + docker.io/federdaemn/${{ matrix.app }}:latest + docker.io/federdaemn/${{ matrix.app }}:${{ steps.set-op.outputs.software-version }} + docker.io/federdaemn/${{ matrix.app }}:${{ steps.set-op.outputs.time-docker }} - # use oras to push artifacthub metadata to ghcr.io + - name: Build image in testing only + uses: docker/build-push-action@v5 + if: github.event_name == 'pull_request' && github.ref != 'refs/heads/main' + with: + # do not push image + push: false + + # use local repository + context: . + + # which containerfile to build from + file: | + ./${{ matrix.app }}/containerfile + + # build args to pass to the build + build-args: | + software_version=${{ steps.set-op.outputs.software-version }} + + # build for many platforms at the same time + platforms: | + linux/amd64 + linux/arm64 + linux/arm/v7 + linux/arm/v6 + + # use oras to push artifacthub metadata to registries # source: https://artifacthub.io/docs/topics/repositories/container-images/#repository-metadata - name: Push metadata + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' run: | oras push \ - ghcr.io/federdaemn/oci-anki-sync:artifacthub.io \ + ghcr.io/federdaemn/${{ matrix.app }}:artifacthub.io \ + --config /dev/null:application/vnd.cncf.artifacthub.config.v1+yaml \ + ${{ matrix.app }}/artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml + oras push \ + docker.io/federdaemn/${{ matrix.app }}:artifacthub.io \ --config /dev/null:application/vnd.cncf.artifacthub.config.v1+yaml \ - artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml + ${{ matrix.app }}/artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml diff --git a/.github/workflows/update-anki-version.yml b/.github/workflows/update-version.yml similarity index 57% rename from .github/workflows/update-anki-version.yml rename to .github/workflows/update-version.yml index f884f80..06352ff 100644 --- a/.github/workflows/update-anki-version.yml +++ b/.github/workflows/update-version.yml @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -name: 'Update anki version in values.yml' +name: 'Update software version in values.yml (GH API)' # run workflow every monday at 00:00 UTC on: @@ -12,11 +12,17 @@ on: jobs: update-version: - name: Update anki version in values.yml + name: Update software version in values.yml # use ubuntu as runner runs-on: ubuntu-latest + strategy: + matrix: + # check for every application using github releases + app: + - anki-sync-server + # add GH token to secrets as GH_ANKI_VERSION_TOKEN # with write access to repository # to allow workflow to write to repository @@ -34,10 +40,12 @@ jobs: - name: Setup yq uses: mikefarah/yq@v4 - - name: Get current anki version - id: anki-version + - name: Get current software version and correct repo + id: set-op run: | - echo "anki-version=$(yq '.version.anki-version' ./values.yml)" \ + echo "software-version=$(yq '.version.software-version' ./${{ matrix.app }}/values.yml)" \ + >> $GITHUB_OUTPUT + echo "gh-repo=$(yq '.repository.software-repository' ./${{ matrix.app }}/values.yml)" \ >> $GITHUB_OUTPUT - name: Fetch GH API and get tag_name from latest release @@ -47,24 +55,24 @@ jobs: tag_name=$(curl -L \ -H "Accept: application/vnd.github+json" \ -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/ankitects/anki/releases/latest |\ + https://api.github.com/repos/${{ steps.set-op.outputs.gh-repo }}/releases/latest |\ yq '.tag_name') # set output for later use echo "name=$tag_name" >> $GITHUB_OUTPUT - - name: Set new anki version in values.yml - if: ${{ steps.anki-version.outputs.anki-version != steps.get-release.outputs.name }} + - name: Set new software version in values.yml + if: ${{ steps.set-op.outputs.software-version != steps.get-release.outputs.name }} run: | - yq -i '.version.anki-version = "${{ steps.get-release.outputs.name }}"' \ - ./values.yml + yq -i '.version.software-version = "${{ steps.get-release.outputs.name }}"' \ + ./${{ matrix.app }}/values.yml - name: Set up git email/name a. commit changes - if: ${{ steps.anki-version.outputs.anki-version != steps.get-release.outputs.name }} + if: ${{ steps.set-op.outputs.software-version != steps.get-release.outputs.name }} run: | git config user.name federdaemn-bot git config user.email federdaemn@mail.de - git add ./values.yml - git commit -m "chore(anki): bump anki version to ${{ steps.get-release.outputs.name }}" \ + git add ./${{ matrix.app }}/values.yml + git commit -m "chore(${{ matrix.app }}): bump version to ${{ steps.get-release.outputs.name }}" \ -m "Signed-off-by: github-actions in the name of Frederik Zorn " git push origin main diff --git a/.reuse/dep5 b/.reuse/dep5 index 6bdd5d5..3dc439f 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -1,7 +1,7 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: oci-anki-sync +Upstream-Name: container Upstream-Contact: Frederik Zorn -Source: https://github.com/federdaemn/oci-anki-sync +Source: https://github.com/federdaemn/container # Sample paragraph, commented out: # @@ -13,6 +13,6 @@ Files: .vscode/* Copyright: 2023 Frederik Zorn License: Apache-2.0 -Files: imgs/anki/logo.png +Files: anki-sync-server/imgs/ah-logo.png Copyright: Alex Fraser https://apps.ankiweb.net/ License: LicenseRef-anki-logo diff --git a/README.md b/README.md index 9c142af..fa88cfe 100644 --- a/README.md +++ b/README.md @@ -4,56 +4,45 @@ SPDX-FileCopyrightText: 2023 Frederik Zorn SPDX-License-Identifier: Apache-2.0 --> -# oci-anki-sync (anki-sync-server docker container) repository +# container repository -This contains a Dockerfile and Ci scripts to build a container image for -[Anki Sync Server](https://apps.ankiweb.net/) using a scratch image as base -image. +This contains dockerfiles and CI/CD scripts to build container images for +various tools. -## Updates and Versions +## Hosted Images + +Currently I have these images built. Read more in the readme of the respective +folder. -* The container is auto-updated every Monday whenever a new version of anki is - released. This is done by a GitHub Action and happens without any manual - intervention or review. -* The actions are also auto-updated through dependabot. -* The image which is used to build is always the latest version of Debian Linux. +| software | official | auto-updates | +| --- | --- | --- | +| anki-sync-server | No | Yes | + +## Updates and Versions -Result: The container is always up-to-date (at least after every Monday) and I -can forget this project exists :). +I try to set up auto-updates for every container but it's not always possible. +This is documented in the readme's of the folders. ## Hosting ### Git This project is hosted on [GitHub](https://github.com) at the -[federdaemn/oci-anki-sync](https://github.com/federdaemn/oci-anki-sync) project. +[federdaemn/containers](https://github.com/federdaemn/containers) project. Every +tool has it's own folder with instructions. ### Container Registry The container images are hosted on -[GitHub Container Registry](https://github.com/federdaemn/oci-anki-sync/pkgs/container/oci-anki-sync) -(recommended) and on -[Docker Hub](https://hub.docker.com/r/federdaemn/oci-anki-sync) for redundancy. -Additionally, the container images are also listed on -[artifacthub.io](https://artifacthub.io) with the package name -[`oci-anki-sync`](https://artifacthub.io/packages/container/oci-anki-sync/oci-anki-sync). - -There are three tags available on both registries: - -* `latest`: Always the latest version of anki. -* ``: The version specified of anki. -* ``: The exact time(+date) when the container was built - (using (`date` syntax): %Y-%m-%dt%H-%M-%Sz). - -## Setup - -* See SETUP.md for detailed instructions. +[GitHub Container Registry](https://github.com/features/packages) (recommended) +and on [Docker Hub](https://hub.docker.com/) for redundancy. Additionally, the +images are listed on [Artifact Hub](https://artifacthub.io). ## Contributing -* Contributions for newer versions or files are gracefully accepted but the - scope is to only generate an auto-updating docker/oci container. -* Please try to wrap lines at 80 characters. +* Contributions for newer versions or files are gracefully accepted. Even things + like small speed improvements are helpfull. +* Please try to wrap all lines at 80 characters. ## License diff --git a/anki-sync-server/README.md b/anki-sync-server/README.md new file mode 100644 index 0000000..013b574 --- /dev/null +++ b/anki-sync-server/README.md @@ -0,0 +1,56 @@ + + +# anki-sync-server folder + +This contains files to build a container image for +[Anki Sync Server](https://apps.ankiweb.net/) using a scratch image as base +image. + +## Updates and Versions + +* The container is auto-updated every Monday whenever a new version of anki is + released. This is done by a GitHub Action and happens without any manual + intervention or review. +* The actions are also auto-updated through dependabot. +* The image which is used to build is always the latest version of Debian Linux. + +Result: The container is always up-to-date (at least after every Monday) and I +can forget this project exists :). + +## Host Architecture + +This image is cross-compiled and thus available for + +* linux/amd64 +* linux/arm64 +* linux/arm/v7 +* linux/arm/v6 + +## Hosting + +### Container Registry + +You can find this image on +[GitHub Container Registry](https://github.com/federdaemn/container/pkgs/container/anki-sync-server) +(recommended) and on +[Docker Hub](https://hub.docker.com/r/federdaemn/anki-sync-server) for redundancy. +The Artifact Hub name is [`anki-sync-server`](https://artifacthub.io/packages/container/anki-sync-server/anki-sync-server). + +There are four tags available: + +* `latest`: Always the latest version of anki. +* ``: The version specified of anki. +* ``: The exact time (+ date) when the container was built + (using (`date` syntax): %Y-%m-%dt%H-%M-%Sz). +* `artifacthub.io`: You may ignore this. This is just for Artifact Hub Verified + Publisher. + +## Setup + +* See SETUP.md for detailed instructions. + +**For anything other please see the [repo readme](https://github.com/federdaemn/container/main/README.md) on GitHub** diff --git a/SETUP.md b/anki-sync-server/SETUP.md similarity index 71% rename from SETUP.md rename to anki-sync-server/SETUP.md index 0210c11..7fd6e72 100644 --- a/SETUP.md +++ b/anki-sync-server/SETUP.md @@ -13,27 +13,27 @@ version: "3.7" services: - oci-anki-sync: - # https://github.com/federdaemn/oci-anki-sync/blob/main/SETUP.md - image: ghcr.io/federdaemn/oci-anki-sync:2.1.66 - container_name: oci-anki-sync + anki-sync-server: + # https://github.com/federdaemn/anki-sync-server/blob/main/SETUP.md + image: ghcr.io/federdaemn/anki-sync-server:2.1.66 + container_name: anki-sync-server restart: unless-stopped # these are sample passwords, please change them environment: - SYNC_USER1=panda:rsfPz4NXELBxmJ - SYNC_USER2=penguin:2Qtf5nnsDpsQ3b volumes: - - oci-anki-sync:/config + - anki-sync-server:/config ports: - 22701:22701 volumes: - oci-anki-sync: + anki-sync-server: ``` * the important parts are * set SYNC_USERX to your desired username and password - * mount volume oci-anki-sync to /config + * mount volume anki-sync-server to /config * open port 22701 **for more configuration options see ** diff --git a/artifacthub-repo.yml b/anki-sync-server/artifacthub-repo.yml similarity index 90% rename from artifacthub-repo.yml rename to anki-sync-server/artifacthub-repo.yml index c685939..c516e03 100644 --- a/artifacthub-repo.yml +++ b/anki-sync-server/artifacthub-repo.yml @@ -9,7 +9,7 @@ # # optional, enables verified publisher -repositoryID: 1c0df0d3-21af-4cb9-aaae-663cdaf93807 +repositoryID: 0e6be73b-431a-4bd8-9220-26400991eee6 # optional, used to claim repository ownership owners: diff --git a/anki-sync-server/containerfile b/anki-sync-server/containerfile new file mode 100644 index 0000000..3753288 --- /dev/null +++ b/anki-sync-server/containerfile @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2023 Frederik Zorn +# +# SPDX-License-Identifier: Apache-2.0 + +# use the official Rust image with debian base as builder +FROM --platform=$BUILDPLATFORM docker.io/library/rust:latest as builder + +# set anki version +ARG software_version + +# make multi-platform args available to process +ARG TARGETARCH +ARG TARGETVARIANT + +# see script +COPY ../tools/convert-arch-cargo.sh . +RUN sh ./convert-arch-cargo.sh + +# upgrade system and install dependency +RUN \ + apt-get update && \ + apt-get upgrade -y && \ + apt-get install protobuf-compiler -y + +# git clone source repository of anki (only last commit, init submodules) +RUN \ + git clone --recurse-submodules --depth 1 --branch $software_version \ + https://github.com/ankitects/anki.git \ + /build + +# set build directory (like cd) +WORKDIR /build + +# build anki-sync-server +# set PROTOC to use the installed protobuf compiler (error if not set) + +# set RUSTFLAGS (--target needed) to build static binary +# source: https://msfjarvis.dev/posts/building-static-rust-binaries-for-linux/ + +# build with release optimizations +# copy binary to standard dir (use cargo build --out when stable) +RUN \ + PROTOC=/usr/bin/protoc RUSTFLAGS='-C target-feature=+crt-static' \ + cargo build --release --target $(cat /.platform.txt) \ + --package anki-sync-server && \ + mkdir -p /output && \ + cp /build/target/$(cat /.platform.txt)/release/anki-sync-server /output/anki-sync-server + +# copy binary container with nothing other to reduce container size +FROM scratch + +# copy binary from builder +COPY --from=builder /output/anki-sync-server /app/anki-sync-server + +ENV \ +# stores data in /config (VOLUME for persistence) + SYNC_BASE="/config" \ +# set default port + SYNC_PORT="27701" + +# switch user for better security +USER anki-sync-server + +# don't forget to set at least SYNC_USER1 +CMD [ "/app/anki-sync-server" ] + +# Unimportant +# specify labels that aren't standardised in .github/workflows/container-build.yml + +LABEL \ + org.opencontainers.image.description="anki-sync-server docker/oci container" \ + org.opencontainers.image.licenses="AGPL-3.0-or-later" \ + io.artifacthub.package.keywords="anki,sync,server,anki-sync-server,anki-sync" \ diff --git a/imgs/anki/logo.png b/anki-sync-server/imgs/ah-logo.png similarity index 100% rename from imgs/anki/logo.png rename to anki-sync-server/imgs/ah-logo.png diff --git a/values.yml b/anki-sync-server/values.yml similarity index 61% rename from values.yml rename to anki-sync-server/values.yml index 3bb79ac..f2176b2 100644 --- a/values.yml +++ b/anki-sync-server/values.yml @@ -7,4 +7,8 @@ version: # anki version to compile and to use as tag - anki-version: 2.1.66 + software-version: 2.1.66 + +repository: + # which repository to check and associate with anki-sync-server + software-repository: ankitects/anki diff --git a/containerfile b/containerfile deleted file mode 100644 index d93abc3..0000000 --- a/containerfile +++ /dev/null @@ -1,52 +0,0 @@ -# SPDX-FileCopyrightText: 2023 Frederik Zorn -# -# SPDX-License-Identifier: Apache-2.0 - -# use the official Rust image with debian base as builder -FROM docker.io/library/rust:latest as builder - -# set anki version -ARG anki_version - -# upgrade system a. install dependency -RUN \ - apt-get update && \ - apt-get upgrade -y && \ - apt-get install protobuf-compiler -y - -# git clone source repository of anki (only last commit, init submodules) -RUN \ - git clone https://github.com/ankitects/anki.git \ - --branch $anki_version --depth 1 --recurse-submodules \ - /build - -# Set build directory (like cd) -WORKDIR /build - -# build anki-sync-server -# set PROTOC to use the installed protobuf compiler (error if not set) - -# set RUSTFLAGS (--target needed) to build static binary -# source: https://msfjarvis.dev/posts/building-static-rust-binaries-for-linux/ - -# build with release optimizations -RUN \ - PROTOC=/usr/bin/protoc RUSTFLAGS='-C target-feature=+crt-static' \ - cargo build --release --target x86_64-unknown-linux-gnu \ - --package anki-sync-server - -# copy binary container with nothing other to reduce container size -FROM scratch - -# copy binary from builder -COPY --from=builder /build/target/x86_64-unknown-linux-gnu/release/anki-sync-server /app/anki-sync-server - -ENV \ -# stores data in /config (VOLUME for persistence) - SYNC_BASE="/config" \ - -# set default port - SYNC_PORT="27701" - -# don't forget to set at least SYNC_USER1 -CMD [ "/app/anki-sync-server" ] diff --git a/tools/convert-arch-cargo.sh b/tools/convert-arch-cargo.sh new file mode 100644 index 0000000..f28ea62 --- /dev/null +++ b/tools/convert-arch-cargo.sh @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2023 Frederik Zorn +# +# SPDX-License-Identifier: Apache-2.0 + +# convert docker-style target architecture (e.g. linux/arm/v7) to +# cargo-style target architecture (e.g. armv7-unknown-linux-gnueabihf) + +# source: https://blog.container-solutions.com/building-multiplatform-container-images + +#!/usr/bin/env sh + +# merge both variables with a / as seperator if the latter exists +if [ -n "$TARGETVARIANT" ]; then + TARGET="$TARGETARCH/$TARGETVARIANT" + else + TARGET="$TARGETARCH" +fi + +# write cargo compatible archs to .platform.txt +case $TARGET in + + "amd64") + echo "x86_64-unknown-linux-gnu" > /.platform.txt + ;; + "arm64") + echo "aarch64-unknown-linux-gnu" > /.platform.txt + ;; + "arm/v7") + echo "armv7-unknown-linux-gnueabihf" > /.platform.txt + ;; + "arm/v6") + echo "arm-unknown-linux-gnueabihf" > /.platform.txt + ;; +esac