diff --git a/.github/workflows/ci.yml b/.github/workflows/docker.yml similarity index 73% rename from .github/workflows/ci.yml rename to .github/workflows/docker.yml index fe122b56..cf11273c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/docker.yml @@ -1,60 +1,10 @@ -name: Lint, test and publish +name: Test and publish docker images on: [push, pull_request] jobs: - php-lint: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 - with: - php-version: '7.4' - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - run: | - composer install --prefer-source --quiet --no-interaction - composer test - - caddy-fmt: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Format caddyfile - run: | - cd development - cp Caddyfile Caddyfile.orig - docker run -v $PWD:/srv caddy \ - caddy fmt --overwrite - diff Caddyfile.orig Caddyfile - - etc-lint: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Get yarn cache - id: yarn-cache - run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT - - uses: actions/cache@v3 - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Lint - run: | - yarn --dev - yarn run lint - docker-image: + docker-images: name: Docker image test and publishing runs-on: ubuntu-22.04 steps: @@ -80,6 +30,7 @@ jobs: - name: Build a test image on amd64 and cache uses: docker/build-push-action@v5 with: + context: "{{defaultContext}}:dockerfiles" platforms: linux/amd64 cache-from: ghcr.io/femiwiki/mediawiki:latest cache-to: mode=max,type=local,dest=/tmp/.buildx-cache @@ -147,6 +98,7 @@ jobs: - name: Build a multi-platform docker image and push uses: docker/build-push-action@v5 with: + context: "{{defaultContext}}:dockerfiles" platforms: linux/amd64,linux/arm64 cache-from: | ghcr.io/femiwiki/mediawiki:latest diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 00000000..d39bacf2 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,53 @@ +on: [push, pull_request] + +jobs: + php-lint: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Setup PHP Action + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + - run: | + composer install --prefer-source --quiet --no-interaction + composer test + + caddy-fmt: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Format caddyfile + run: | + cd development + cp Caddyfile Caddyfile.orig + docker run -v $PWD:/srv caddy \ + caddy fmt --overwrite + diff Caddyfile.orig Caddyfile + + etc-lint: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Get yarn cache + id: yarn-cache + run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + - name: Lint + run: | + yarn --dev + yarn run lint diff --git a/dockerfiles/Dockerfile b/dockerfiles/Dockerfile new file mode 100644 index 00000000..630bad5f --- /dev/null +++ b/dockerfiles/Dockerfile @@ -0,0 +1,218 @@ +ARG MEDIAWIKI_VERSION=1.41.0 +ARG CADDY_MWCACHE_COMMIT=9e9ac234170400406c6a328bbaaaa4c95e05bd73 + +ARG TINI_VERSION=0.18.0 + +# +# 미디어위키 확장 설치 스테이지. 루비 스크립트를 이용해 수많은 미디어위키 +# 확장들을 병렬로 빠르게 미리 다운받아 놓는다. +# +FROM --platform=$TARGETPLATFORM ruby:3.3.0-alpine AS base-extension + +# ARG instructions without a value inside of a build stage to use the default +# value of an ARG declared before the first FROM use +ARG MEDIAWIKI_VERSION + +# aria2 +# +# References: +# https://aria2.github.io/ +RUN apk update && apk add \ + aria2 + +# Install aria2.conf +COPY extension-installer/aria2.conf /root/.config/aria2/aria2.conf + +RUN mkdir /mediawiki/ + +# Extensions and skins setup +COPY extension-installer/* / +RUN bundle config set deployment 'true' &&\ + bundle config set without 'development test' &&\ + bundle install +RUN MEDIAWIKI_BRANCH="REL$(echo $MEDIAWIKI_VERSION | cut -d. -f-2 | sed 's/\./_/g')" &&\ + bundle exec ruby /install_extensions.rb "${MEDIAWIKI_BRANCH}" + +# +# Composer 스테이지. Composer 이미지는 PHP 버전을 따로 설정할 수 없어 스테이지를 생성해 +# /usr/bin/composer만 복사해 사용하여야 합니다. +# See 'PHP version & extensions' section on https://hub.docker.com/_/composer for more details. +# +FROM --platform=$TARGETPLATFORM composer:2.6.6 AS composer + +# +# 미디어위키 다운로드 스테이지. 다운받은 확장기능에 더해 미디어위키를 추가로 받고 +# Composer로 디펜던시들을 설치한다. +# +FROM --platform=$TARGETPLATFORM php:8.1.22-cli AS base-mediawiki + +ARG MEDIAWIKI_VERSION + +# Install dependencies and utilities +RUN apt-get update && apt-get install -y \ + libicu-dev \ + # https://getcomposer.org/doc/00-intro.md#system-requirements + git \ + unzip + +# Install the PHP extensions we need +RUN IPE_DEBUG=1 docker-php-ext-install -j8 \ + intl \ + calendar + +COPY --from=base-extension /mediawiki /tmp/mediawiki + +# Create a cache directory for composer +RUN mkdir -p /tmp/composer + +# MediaWiki setup +RUN MEDIAWIKI_MAJOR_VERSION="$(echo $MEDIAWIKI_VERSION | cut -d. -f-2)" &&\ + curl -fSL "https://releases.wikimedia.org/mediawiki/${MEDIAWIKI_MAJOR_VERSION}/mediawiki-core-${MEDIAWIKI_VERSION}.tar.gz" -o mediawiki.tar.gz &&\ + tar -xzf mediawiki.tar.gz --strip-components=1 --directory /tmp/mediawiki/ &&\ + rm mediawiki.tar.gz +COPY configs/composer.local.json /tmp/mediawiki/ + +COPY --from=composer /usr/bin/composer /usr/bin/composer +RUN COMPOSER_HOME=/tmp/composer /usr/bin/composer update --no-dev --working-dir '/tmp/mediawiki' + +# +# Caddy 스테이지. Route53와 caddy-mwcache 패키지를 설치한 Caddy를 빌드한다. +# +FROM --platform=$TARGETPLATFORM caddy:2-builder AS caddy +ARG CADDY_MWCACHE_COMMIT + +RUN XCADDY_DEBUG=1 xcaddy build v2.7.5 \ + --with github.com/caddy-dns/route53 \ + --with "github.com/femiwiki/caddy-mwcache@${CADDY_MWCACHE_COMMIT}" + +# +# 미디어위키 도커이미지 생성 스테이지. 미디어위키 실행에 필요한 각종 PHP +# 디펜던시들을 설치한다. +# +# 파일 목록: +# /usr/local/etc/php PHP 설정 +# /srv/femiwiki.com 미디어위키 소스코드 및 확장들 +# /usr/local/{bin,sbin} 임의로 설치한 실행파일들 +# /tmp/cache 캐시 디렉토리 +# /var/log/cron.log 크론 로그 +# /tini tini +# +FROM --platform=$TARGETPLATFORM php:8.1.22-fpm +ARG TARGETPLATFORM +ARG TINI_VERSION + +# Install dependencies and utilities +RUN apt-get update && apt-get install -y \ + # Build dependencies + build-essential \ + libicu-dev \ + # Runtime depenencies + imagemagick \ + librsvg2-bin \ + # See https://github.com/femiwiki/docker-mediawiki/issues/442 + git \ + # Required for SyntaxHighlighting + python3 \ + # Required for Scribunto when the machine is on aarch64 architecture + # Only 5.1.x is supported + # Reference: https://www.mediawiki.org/wiki/Extension:Scribunto#Additional_binaries + lua5.1 \ + # CLI utilities + cron \ + sudo + +# Install Caddy +COPY --from=caddy /usr/bin/caddy /usr/bin/caddy + +RUN mkdir -p \ + /config/caddy \ + /data/caddy \ + /etc/caddy \ + /usr/share/caddy + +# See https://caddyserver.com/docs/conventions#file-locations for details +ENV XDG_CONFIG_HOME /config +ENV XDG_DATA_HOME /data + +# Install the PHP extensions we need +RUN docker-php-ext-install -j8 \ + mysqli \ + opcache \ + intl \ + sockets \ + calendar + +# Install the default object cache +RUN pecl channel-update pecl.php.net +RUN pecl install apcu +RUN docker-php-ext-enable apcu + +# +# Tini +# +# See https://github.com/krallin/tini for the further details +RUN PLATFORM="$(echo $TARGETPLATFORM | cut -d/ -f2)" &&\ + curl -sLfo /tini "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-${PLATFORM}" +RUN chmod +x /tini +ENTRYPOINT ["/tini", "--"] + +# Remove packages which is not needed anymore (build dependencies of PHP extensions) +ONBUILD RUN apt-get autoremove -y --purge \ + build-essential \ + libicu-dev + +# Set timezone +ENV TZ=Asia/Seoul +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Prepare PHP log +RUN touch /var/log/php-fpm.log &&\ + chown www-data:www-data /var/log/php-fpm.log + +# Install Mediawiki and extensions +COPY --from=base-mediawiki --chown=www-data /tmp/mediawiki /srv/femiwiki.com + +# Create cache directories for mediawiki +# $wgCacheDirectory should not be accessible from the web and writable by the web server +# See https://www.mediawiki.org/wiki/Manual:$wgCacheDirectory for details +RUN sudo -u www-data mkdir -p /tmp/file-cache /tmp/cache + +# Web server should be able to write 'extensions/Widgets/compiled_templates' +# directory Required by 'Widgets' extension +# Reference: https://www.mediawiki.org/wiki/Extension:Widgets +RUN chmod o+w /srv/femiwiki.com/extensions/Widgets/compiled_templates + +# Web server should be able to execute lua binary +# Reference: https://www.mediawiki.org/wiki/Extension:Scribunto#Additional_binaries +RUN chmod o+x /usr/bin/lua + + +# +# Install and register cron +# +COPY cron/crontab /tmp/crontab +RUN crontab /tmp/crontab && rm /tmp/crontab + +# Install scripts +RUN sudo -u www-data mkdir -p /srv/femiwiki.com/sitemap +COPY cron/generate-sitemap \ + cron/update-special-pages \ + cron/run-jobs \ + /usr/local/bin/ + +# Ship femiwiki resources +COPY --chown=www-data:www-data resources /srv/femiwiki.com/ + +# Ship femiwiki-specific mediawiki configurations +COPY --chown=www-data [ "configs/LocalSettings.php", "configs/Hotfix.php", "configs/site-list.xml", "/a/" ] +# secret.php should be mounted to '/a/secret.php' +VOLUME /a + +WORKDIR /srv/femiwiki.com + +EXPOSE 80 +EXPOSE 443 +EXPOSE 9000 + +COPY run /usr/local/bin/ +CMD ["/usr/local/bin/run"]