diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..c2d78c6 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,167 @@ +name: Docker build and push + +# limit concurrency +# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#examples-using-concurrency-and-the-default-behavior +concurrency: docker_canasta_maintenance + +on: + push: + # Only activate for `master` branch + branches: + - main + # Plus for all tags + tags: + - '*' + + # Plus for any pull-requests + pull_request: + +env: + IMAGE_NAME: canasta-maintenance + +jobs: + # Test the image Dockerfile syntax using https://github.com/replicatedhq/dockerfilelint + test: + runs-on: ubuntu-latest + if: github.event_name == 'push' || github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v3 + - + name: Run linter (hadolint) + uses: vedmaka/hadolint-action@master + with: + dockerfile: "Dockerfile" + config: "hadolint.yaml" + + # Push image to GitHub Packages. + # The image tag pattern is: + # for pull-requests: --, eg: 1.35.2-20210125-25 + # for tags: + # for `master` branch: latest + -latest + -- + # being parsed from the Dockerfile + push: + needs: [test] + runs-on: ubuntu-latest + if: github.event_name == 'push' || github.event_name == 'pull_request' + steps: + - name: Checkout + uses: actions/checkout@v3 + - + name: Generate tags + id: generate + run: | + + # Image ID + IMAGE_ID=ghcr.io/canastawiki/$IMAGE_NAME + + # Date + BDATE=$(date +%Y%m%d) + + # Extract MW version from Dockerfile + MEDIAWIKI_VERSION=$(sed -nr 's/MW_CORE_VERSION\=([0-9\.]+)/\1/p' Dockerfile | sed "s/ \\\//" | sed "s/\t//") + # Extract MW major version (like 1.35) + MEDIAWIKI_MAJOR_VERSION=${MEDIAWIKI_VERSION%.*} + + # Change all uppercase to lowercase, just in case + IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') + + # Strip git ref prefix from version and use it as suffix for version + VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + + # Get the Canasta version from the "VERSION" file + CANASTA_VERSION=$(cat VERSION) + + # For pull requests just extract the PR number + PR_NUMBER="" + [ "${{ github.event_name }}" == "pull_request" ] && VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\)/merge,\1,') + [ "${{ github.event_name }}" == "pull_request" ] && PR_NUMBER=$VERSION + + # Append version + [ "${{ github.event_name }}" == "pull_request" ] && VERSION=$MEDIAWIKI_VERSION-$BDATE-$VERSION + + # Strip "v" prefix from tag name if it's a tag + # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') + + # Use Docker `latest` tag convention if it's a master branch build + [ "$VERSION" == "master" ] && VERSION=latest + + # Compose REGISTRY_TAGS variable + REGISTRY_TAGS=$IMAGE_ID:$VERSION + + # For master branch also supply an extra tag: -latest,-- + [ "$VERSION" == "latest" ] && REGISTRY_TAGS=$REGISTRY_TAGS,$IMAGE_ID:$CANASTA_VERSION,$IMAGE_ID:$MEDIAWIKI_MAJOR_VERSION-latest,$IMAGE_ID:$MEDIAWIKI_VERSION-latest,$IMAGE_ID:$MEDIAWIKI_VERSION-$BDATE-$(git rev-parse --short HEAD) + + echo IMAGE_ID=$IMAGE_ID + echo VERSION=$VERSION + echo REGISTRY_TAGS=$REGISTRY_TAGS + echo headref=${{ github.head_ref }} + + SHA_SHORT=${{ github.sha }} + [ "${{ github.event_name }}" == "pull_request" ] && SHA_SHORT=$(echo ${{ github.event.pull_request.head.sha }} | cut -c1-8) + + echo "Final image tag to be pushed:" + echo $REGISTRY_TAGS + echo "REGISTRY_TAGS=$REGISTRY_TAGS" >> $GITHUB_OUTPUT + echo "REGISTRY_TAGS_VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "REGISTRY_TAGS_PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT + echo "SHA_SHORT=$SHA_SHORT" >> $GITHUB_OUTPUT + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + install: true + - + name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + - + name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - + name: Build and push + id: docker_build + uses: docker/build-push-action@v3 + with: + context: . + platforms: linux/amd64, linux/arm64 + push: true + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new + tags: ${{ steps.generate.outputs.REGISTRY_TAGS }} + - + # 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 + - + name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} + - + name: Image tags debug + run: echo ${{ steps.generate.outputs.REGISTRY_TAGS }} + + - + name: Notify about image tag + if: github.event_name == 'pull_request' && steps.docker_build.outputs.digest != '' + uses: hasura/comment-progress@v2.2.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + repository: ${{ github.repository }} + number: ${{ github.event.number }} + id: comment + message: ":whale: The image based on [${{ steps.generate.outputs.SHA_SHORT }}](https://github.com/WikiTeq/docker-wikiteq-canasta/pull/${{ steps.generate.outputs.REGISTRY_TAGS_PR_NUMBER }}/commits/${{ github.event.pull_request.head.sha }}) commit has been built with `${{ steps.generate.outputs.REGISTRY_TAGS_VERSION }}` tag as [${{ steps.generate.outputs.REGISTRY_TAGS }}](https://github.com/${{ github.repository }}/pkgs/container/${{ env.IMAGE_NAME }}/${{ steps.docker_build.outputs.imageid }}?tag=${{ steps.generate.outputs.REGISTRY_TAGS_VERSION }})" + recreate: true + fail: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24a5841 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Editors +*.kate-swp +*~ +\#*# +.#* +.*.swp +.project +cscope.files +cscope.out +*.orig +.desktop +.directory + +# Contains private data +/.env +/docker-compose.override.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3e9f960 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,655 @@ +FROM debian:11.5 as base + +LABEL maintainers="" +LABEL org.opencontainers.image.source=https://github.com/CanastaWiki/Canasta-Maintenance + +ENV MW_VERSION=REL1_39 \ + MW_CORE_VERSION=1.39.1 \ + WWW_ROOT=/var/www/mediawiki \ + MW_HOME=/var/www/mediawiki/w \ + MW_ORIGIN_FILES=/mw_origin_files \ + MW_VOLUME=/mediawiki \ + WWW_USER=www-data \ + WWW_GROUP=www-data + +# System setup +RUN set x; \ + apt-get clean \ + && apt-get update \ + && apt-get install -y aptitude \ + && aptitude -y upgrade \ + && aptitude install -y \ + git \ + software-properties-common \ + gpg \ + apt-transport-https \ + ca-certificates \ + wget \ + imagemagick \ + librsvg2-bin \ + python3-pygments \ + msmtp \ + msmtp-mta \ + patch \ + vim \ + mc \ + ffmpeg \ + curl \ + iputils-ping \ + unzip \ + gnupg \ + default-mysql-client \ + rsync \ + lynx \ + poppler-utils \ + && aptitude update \ + && aptitude install -y \ + php7.4 \ + php7.4-mysql \ + php7.4-cli \ + php7.4-gd \ + php7.4-mbstring \ + php7.4-xml \ + php7.4-mysql \ + php7.4-intl \ + php7.4-opcache \ + php7.4-apcu \ + php7.4-redis \ + php7.4-curl \ + php7.4-zip \ + php7.4-fpm \ + && aptitude clean \ + && rm -rf /var/lib/apt/lists/* + +# Post install configuration +RUN set -x; \ + # Create directories + mkdir -p $MW_HOME \ + && mkdir -p $MW_ORIGIN_FILES \ + && mkdir -p $MW_VOLUME + +# Composer +RUN set -x; \ + curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ + && composer self-update 2.1.3 + +FROM base as source + +# MediaWiki core +RUN set -x; \ + git clone --depth 1 -b $MW_CORE_VERSION https://gerrit.wikimedia.org/r/mediawiki/core.git $MW_HOME \ + && cd $MW_HOME \ + && git submodule update --init --recursive + +# Skins +# The Minerva Neue, MonoBook, Timeless, Vector and Vector 2022 skins are bundled into MediaWiki and do not need to be +# separately installed. +# The Chameleon skin is downloaded via Composer and also does not need to be installed. +RUN set -x; \ + cd $MW_HOME/skins \ + # CologneBlue + && git clone -b $MW_VERSION --single-branch https://gerrit.wikimedia.org/r/mediawiki/skins/CologneBlue $MW_HOME/skins/CologneBlue \ + && cd $MW_HOME/skins/CologneBlue \ + && git checkout -q 4d588eb78d7e64e574f631c5897579537305437d \ + # Modern + && git clone -b $MW_VERSION --single-branch https://gerrit.wikimedia.org/r/mediawiki/skins/Modern $MW_HOME/skins/Modern \ + && cd $MW_HOME/skins/Modern \ + && git checkout -q fb6c2831b5f150e9b82d98d661710695a2d0f8f2 \ + # Pivot + && git clone -b v2.3.0 https://github.com/wikimedia/mediawiki-skins-Pivot $MW_HOME/skins/pivot \ + && cd $MW_HOME/skins/pivot \ + && git checkout -q d79af7514347eb5272936243d4013118354c85c1 \ + # Refreshed + && git clone -b $MW_VERSION --single-branch https://gerrit.wikimedia.org/r/mediawiki/skins/Refreshed $MW_HOME/skins/Refreshed \ + && cd $MW_HOME/skins/Refreshed \ + && git checkout -q 86f33620f25335eb62289aa18d342ff3b980d8b8 + +# Extensions +# The following extensions are bundled into MediaWiki and do not need to be separately installed (though in some cases +# they are modified): AbuseFilter, CategoryTree, Cite, CiteThisPage, CodeEditor, ConfirmEdit, Gadgets, ImageMap, +# InputBox, Interwiki, LocalisationUpdate, Math, MultimediaViewer, Nuke, OATHAuth, PageImages, ParserFunctions, +# PdfHandler, Poem, Renameuser, Replace Text, Scribunto, SecureLinkFixer, SpamBlacklist, SyntaxHighlight, TemplateData, +# TextExtracts, TitleBlacklist, VisualEditor, WikiEditor. +# The following extensions are downloaded via Composer and also do not need to be downloaded here: Bootstrap, +# BootstrapComponents, Maps, Mermaid, Semantic Breadcrumb Links, Semantic Compound Queries, Semantic Extra Special +# Properties, Semantic MediaWiki (along with all its helper library extensions, like DataValues), Semantic Result +# Formats, Semantic Scribunto, SimpleBatchUpload, SubPageList. +RUN set -x; \ + cd $MW_HOME/extensions \ + # AdminLinks + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/AdminLinks $MW_HOME/extensions/AdminLinks \ + && cd $MW_HOME/extensions/AdminLinks \ + && git checkout -q ad7805941ee29378484d1ef3595041f7d2c15913 \ + # AdvancedSearch + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/AdvancedSearch $MW_HOME/extensions/AdvancedSearch \ + && cd $MW_HOME/extensions/AdvancedSearch \ + && git checkout -q 1a44eafc93a17938333b74a37cb4deff2192e50a \ + # AJAXPoll + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/AJAXPoll $MW_HOME/extensions/AJAXPoll \ + && cd $MW_HOME/extensions/AJAXPoll \ + && git checkout -q 8429d8d4cba5be6df04e3fec17b0daabbf10cfa7 \ + # AntiSpoof + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/AntiSpoof $MW_HOME/extensions/AntiSpoof \ + && cd $MW_HOME/extensions/AntiSpoof \ + && git checkout -q 01cf89a678d5bab6610d24e07d3534356a5880cb \ + # ApprovedRevs (v. 1.8.1) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/ApprovedRevs $MW_HOME/extensions/ApprovedRevs \ + && cd $MW_HOME/extensions/ApprovedRevs \ + && git checkout -q a8cb4bd840465a7db1e10654a0969cfc961d8428 \ + # Arrays + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Arrays $MW_HOME/extensions/Arrays \ + && cd $MW_HOME/extensions/Arrays \ + && git checkout -q 338f661bf0ab377f70e029079f2c5c5b370219df \ + # BetaFeatures + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/BetaFeatures $MW_HOME/extensions/BetaFeatures \ + && cd $MW_HOME/extensions/BetaFeatures \ + && git checkout -q 09cca44341f9695446c4e9fc9e8fec3fdcb197b0 \ + # BreadCrumbs2 + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/BreadCrumbs2 $MW_HOME/extensions/BreadCrumbs2 \ + && cd $MW_HOME/extensions/BreadCrumbs2 \ + && git checkout -q d53357a6839e94800a617de4fc451b6c64d0a1c8 \ + # Cargo (v. 3.4.1) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/Cargo $MW_HOME/extensions/Cargo \ + && cd $MW_HOME/extensions/Cargo \ + && git checkout -q 04bfe84ef4dc806eab0ec52b361a78542d799474 \ + # CharInsert + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/CharInsert $MW_HOME/extensions/CharInsert \ + && cd $MW_HOME/extensions/CharInsert \ + && git checkout -q 54c0f0ca9119a3ce791fb5d53edd4ec32035a5c5 \ + # CheckUser + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/CheckUser $MW_HOME/extensions/CheckUser \ + && cd $MW_HOME/extensions/CheckUser \ + && git checkout -q 9e2b6d3e928855247700146273d8131e025de918 \ + # CirrusSearch + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/CirrusSearch $MW_HOME/extensions/CirrusSearch \ + && cd $MW_HOME/extensions/CirrusSearch \ + && git checkout -q 8296300873aaffe815800cf05c84fa04c8cbd2c0 \ + # CodeMirror + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeMirror $MW_HOME/extensions/CodeMirror \ + && cd $MW_HOME/extensions/CodeMirror \ + && git checkout -q 27efed79972ca181a194d17f4a94f4192fd5a493 \ + # Collection + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Collection $MW_HOME/extensions/Collection \ + && cd $MW_HOME/extensions/Collection \ + && git checkout -q e00e70c6fcec963c8876e410e52c83c75ed60827 \ + # CommentStreams + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/CommentStreams $MW_HOME/extensions/CommentStreams \ + && cd $MW_HOME/extensions/CommentStreams \ + && git checkout -q 274bb10bc2d39fd137650dbc0dfc607c766d1aaa \ + # CommonsMetadata + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/CommonsMetadata $MW_HOME/extensions/CommonsMetadata \ + && cd $MW_HOME/extensions/CommonsMetadata \ + && git checkout -q 8ee30de3b1cabbe55c484839127493fd5fa5d076 \ + # ConfirmAccount + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/ConfirmAccount $MW_HOME/extensions/ConfirmAccount \ + && cd $MW_HOME/extensions/ConfirmAccount \ + && git checkout -q c06d5dfb43811a2dee99099476c57af2b6d762c4 \ + # ContactPage + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/ContactPage $MW_HOME/extensions/ContactPage \ + && cd $MW_HOME/extensions/ContactPage \ + && git checkout -q f509796056ae1fc597b6e3c3c268fac35bf66636 \ + # ContributionScores + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/ContributionScores $MW_HOME/extensions/ContributionScores \ + && cd $MW_HOME/extensions/ContributionScores \ + && git checkout -q e307850555ef313f623dde6e2f1d5d2a43663730 \ + # CookieWarning + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/CookieWarning $MW_HOME/extensions/CookieWarning \ + && cd $MW_HOME/extensions/CookieWarning \ + && git checkout -q bc991e93133bd69fe45e07b3d4554225decc7dae \ + # DataTransfer + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/DataTransfer $MW_HOME/extensions/DataTransfer \ + && cd $MW_HOME/extensions/DataTransfer \ + && git checkout -q 2f9f949f71f0bb7d1bd8b6b97c795b9428bb1c71 \ + # DeleteBatch + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/DeleteBatch $MW_HOME/extensions/DeleteBatch \ + && cd $MW_HOME/extensions/DeleteBatch \ + && git checkout -q 82078d60fc59a718f429ddebe5e99de8a8734413 \ + # Description2 + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Description2 $MW_HOME/extensions/Description2 \ + && cd $MW_HOME/extensions/Description2 \ + && git checkout -q d2a5322a44f940de873050573e35fba4eb3063f8 \ + # Disambiguator + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Disambiguator $MW_HOME/extensions/Disambiguator \ + && cd $MW_HOME/extensions/Disambiguator \ + && git checkout -q b7e7fad5f9f3dccfb902a3cbfd3bf2b16df91871 \ + # DismissableSiteNotice + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/DismissableSiteNotice $MW_HOME/extensions/DismissableSiteNotice \ + && cd $MW_HOME/extensions/DismissableSiteNotice \ + && git checkout -q 88129f80f077ec9e4932148056c8cfc1ed0361c7 \ + # DisplayTitle + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/DisplayTitle $MW_HOME/extensions/DisplayTitle \ + && cd $MW_HOME/extensions/DisplayTitle \ + && git checkout -q a14c406cc273c73a12957b55a27c095ad98d1795 \ + # Echo + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo $MW_HOME/extensions/Echo \ + && cd $MW_HOME/extensions/Echo \ + && git checkout -q fdbc2cafdc412dc60d4345511defe9ee393efecf \ + # Editcount + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Editcount $MW_HOME/extensions/Editcount \ + && cd $MW_HOME/extensions/Editcount \ + && git checkout -q 41544ffceb1356f91575dc6772a48b172751d7cc \ + # Elastica + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Elastica $MW_HOME/extensions/Elastica \ + && cd $MW_HOME/extensions/Elastica \ + && git checkout -q e4ead38b71ed4f3df8dc689fe448b749771b4ed4 \ + # EmailAuthorization + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/EmailAuthorization $MW_HOME/extensions/EmailAuthorization \ + && cd $MW_HOME/extensions/EmailAuthorization \ + && git checkout -q 2016da1b354f741d89b5dc207d4a84e11ffe9bce \ + # EmbedVideo + && git clone --single-branch -b master https://gitlab.com/hydrawiki/extensions/EmbedVideo.git $MW_HOME/extensions/EmbedVideo \ + && cd $MW_HOME/extensions/EmbedVideo \ + && git checkout -q 954af96d3744d8adc7ff6458a05e579784f2d991 \ + # EventLogging + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/EventLogging $MW_HOME/extensions/EventLogging \ + && cd $MW_HOME/extensions/EventLogging \ + && git checkout -q 2740dbcd139be279ca2a4db039739b4f796b4178 \ + # EventStreamConfig + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/EventStreamConfig $MW_HOME/extensions/EventStreamConfig \ + && cd $MW_HOME/extensions/EventStreamConfig \ + && git checkout -q 1aae8cb6c312e49f0126091a59a453cb224657f9 \ + # ExternalData (v. 3.2) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/ExternalData $MW_HOME/extensions/ExternalData \ + && cd $MW_HOME/extensions/ExternalData \ + && git checkout -q 5d30e60a65ca53a3fb5b39826deb2e6917892e22 \ + # FlexDiagrams + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/FlexDiagrams $MW_HOME/extensions/FlexDiagrams \ + && cd $MW_HOME/extensions/FlexDiagrams \ + && git checkout -q 550d0de3e2525d42952d7bc9d291b26455fe07ce \ + # GlobalNotice + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/GlobalNotice $MW_HOME/extensions/GlobalNotice \ + && cd $MW_HOME/extensions/GlobalNotice \ + && git checkout -q 15a40bff4641f00a5a8dda3d36795b1c659c19a7 \ + # GoogleAnalyticsMetrics + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/GoogleAnalyticsMetrics $MW_HOME/extensions/GoogleAnalyticsMetrics \ + && cd $MW_HOME/extensions/GoogleAnalyticsMetrics \ + && git checkout -q 82a08cc63ec58698f144be7c2fb1a6f861cb57bd \ + # GoogleDocCreator + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/GoogleDocCreator $MW_HOME/extensions/GoogleDocCreator \ + && cd $MW_HOME/extensions/GoogleDocCreator \ + && git checkout -q 9e53ecfa4149688a2352a7898c2a2005632e1b7d \ + # Graph + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Graph $MW_HOME/extensions/Graph \ + && cd $MW_HOME/extensions/Graph \ + && git checkout -q 9c229eafdf406c95a4a666a6b7f2a9d0d3d682e4 \ + # HeaderFooter + && git clone https://github.com/enterprisemediawiki/HeaderFooter.git $MW_HOME/extensions/HeaderFooter \ + && cd $MW_HOME/extensions/HeaderFooter \ + && git checkout -q eee7d2c1a3373c7d6b326fd460e5d4859dd22c40 \ + # HeaderTabs (v2.2) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/HeaderTabs $MW_HOME/extensions/HeaderTabs \ + && cd $MW_HOME/extensions/HeaderTabs \ + && git checkout -q 42aaabf1deeb0a228fc99e578ff7ec925e560dd7 \ + # HTMLTags + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/HTMLTags $MW_HOME/extensions/HTMLTags \ + && cd $MW_HOME/extensions/HTMLTags \ + && git checkout -q b8cb3131c5e76f5c037c8474fe14e51f2e877f03 \ + # LabeledSectionTransclusion + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LabeledSectionTransclusion $MW_HOME/extensions/LabeledSectionTransclusion \ + && cd $MW_HOME/extensions/LabeledSectionTransclusion \ + && git checkout -q 187abfeaafbad35eed4254f7a7ee0638980e932a \ + # LDAPAuthentication2 + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LDAPAuthentication2 $MW_HOME/extensions/LDAPAuthentication2 \ + && cd $MW_HOME/extensions/LDAPAuthentication2 \ + && git checkout -q 6bc584893d3157d5180e0e3ed93c3dbbc5b93056 \ + # LDAPAuthorization + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LDAPAuthorization $MW_HOME/extensions/LDAPAuthorization \ + && cd $MW_HOME/extensions/LDAPAuthorization \ + && git checkout -q e6815d29c22f4b4eb85f868372a729ad49d7d3c8 \ + # LDAPProvider + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LDAPProvider $MW_HOME/extensions/LDAPProvider \ + && cd $MW_HOME/extensions/LDAPProvider \ + && git checkout -q 80f8cc8156b0cd250d0dfacd9378ed0db7c2091d \ + # Lingo + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Lingo $MW_HOME/extensions/Lingo \ + && cd $MW_HOME/extensions/Lingo \ + && git checkout -q a291fa25822097a4a2aefff242a876edadb535a4 \ + # LinkSuggest + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LinkSuggest $MW_HOME/extensions/LinkSuggest \ + && cd $MW_HOME/extensions/LinkSuggest \ + && git checkout -q 6005d191e35d1d6bed5a4e7bd1bedc5fa0030bf1 \ + # LinkTarget + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LinkTarget $MW_HOME/extensions/LinkTarget \ + && cd $MW_HOME/extensions/LinkTarget \ + && git checkout -q e5d592dcc72a00e06604ee3f65dfb8f99977c156 \ + # Linter + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Linter $MW_HOME/extensions/Linter \ + && cd $MW_HOME/extensions/Linter \ + && git checkout -q 8bc1727955da7468f096aa5c5b5790923db43d20 \ + # LockAuthor + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LockAuthor $MW_HOME/extensions/LockAuthor \ + && cd $MW_HOME/extensions/LockAuthor \ + && git checkout -q 4ebc4f221a0987b64740014a9380e9c3522f271d \ + # Lockdown + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Lockdown $MW_HOME/extensions/Lockdown \ + && cd $MW_HOME/extensions/Lockdown \ + && git checkout -q ffcb6e8892ad35bb731fad1dc24712a245ab86d0 \ + # LookupUser + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/LookupUser $MW_HOME/extensions/LookupUser \ + && cd $MW_HOME/extensions/LookupUser \ + && git checkout -q 5fa17d449b6bedb3e8cee5b239af6cadae31da70 \ + # Loops + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Loops $MW_HOME/extensions/Loops \ + && cd $MW_HOME/extensions/Loops \ + && git checkout -q 0eb05a81b9b53f5381eefb4f8b6959b6dcdec1d8 \ + # MagicNoCache + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/MagicNoCache $MW_HOME/extensions/MagicNoCache \ + && cd $MW_HOME/extensions/MagicNoCache \ + && git checkout -q 93534c12dac0e821c46c94b21053d274a6e557de \ + # MassMessage + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/MassMessage $MW_HOME/extensions/MassMessage \ + && cd $MW_HOME/extensions/MassMessage \ + && git checkout -q d6a86291bb975c3dc7778f370006f1145cc834bd \ + # MassMessageEmail + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/MassMessageEmail $MW_HOME/extensions/MassMessageEmail \ + && cd $MW_HOME/extensions/MassMessageEmail \ + && git checkout -q edd96f14c6d108d56bcecb18b5bb7b3355437732 \ + # MediaUploader + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/MediaUploader $MW_HOME/extensions/MediaUploader \ + && cd $MW_HOME/extensions/MediaUploader \ + && git checkout -q 1edd91c506c1c0319e7b9a3e71d639130760b1fd \ + # MintyDocs (1.0) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/MintyDocs $MW_HOME/extensions/MintyDocs \ + && cd $MW_HOME/extensions/MintyDocs \ + && git checkout -q 4496e33ce71d2c364b16599619c961a1a330bf14 \ + # MobileFrontend + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/MobileFrontend $MW_HOME/extensions/MobileFrontend \ + && cd $MW_HOME/extensions/MobileFrontend \ + && git checkout -q f0bed5588f76b827038fb9af73fb9677e5804077 \ + # MsUpload + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/MsUpload $MW_HOME/extensions/MsUpload \ + && cd $MW_HOME/extensions/MsUpload \ + && git checkout -q dac2376a2fac6ddf4b2038db9b4bc06092ecaa15 \ + # MyVariables + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/MyVariables $MW_HOME/extensions/MyVariables \ + && cd $MW_HOME/extensions/MyVariables \ + && git checkout -q 8b45be10c9b0a484824c55d8cc48399290384260 \ + # NewUserMessage + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/NewUserMessage $MW_HOME/extensions/NewUserMessage \ + && cd $MW_HOME/extensions/NewUserMessage \ + && git checkout -q 206f32880fa7bf70b191d33ed80b8626bca39efe \ + # NumerAlpha + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/NumerAlpha $MW_HOME/extensions/NumerAlpha \ + && cd $MW_HOME/extensions/NumerAlpha \ + && git checkout -q 93c0869735581006a3f510096738e262d49f4107 \ + # OpenGraphMeta + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/OpenGraphMeta $MW_HOME/extensions/OpenGraphMeta \ + && cd $MW_HOME/extensions/OpenGraphMeta \ + && git checkout -q d319702cd4ceda1967c233ef8e021b67b3fc355f \ + # OpenIDConnect + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/OpenIDConnect $MW_HOME/extensions/OpenIDConnect \ + && cd $MW_HOME/extensions/OpenIDConnect \ + && git checkout -q 0824f3cf3800f63e930abf0f03baf1a7c755a270 \ + # PageExchange + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/PageExchange $MW_HOME/extensions/PageExchange \ + && cd $MW_HOME/extensions/PageExchange \ + && git checkout -q 28482410564e38d2b97ab7321e99c4281c6e5877 \ + # PageForms (v. 5.6) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/PageForms $MW_HOME/extensions/PageForms \ + && cd $MW_HOME/extensions/PageForms \ + && git checkout -q d9b0e47a83d951c585f95c97ea10ea8be95adec9 \ + # PluggableAuth + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/PluggableAuth $MW_HOME/extensions/PluggableAuth \ + && cd $MW_HOME/extensions/PluggableAuth \ + && git checkout -q 4be1e402e1862d165a4feb003c492ddc9525057e \ + # Popups + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Popups $MW_HOME/extensions/Popups \ + && cd $MW_HOME/extensions/Popups \ + && git checkout -q ff4d2156e1f7f4c11f7396cb0cd70d387abd8187 \ + # RegularTooltips + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/RegularTooltips $MW_HOME/extensions/RegularTooltips \ + && cd $MW_HOME/extensions/RegularTooltips \ + && git checkout -q 1af807bb6d5cfbd1e471e38bf70d6a392fb7eda2 \ + # RevisionSlider + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/RevisionSlider $MW_HOME/extensions/RevisionSlider \ + && cd $MW_HOME/extensions/RevisionSlider \ + && git checkout -q 3cae51a322a5ca0f359e83efcb5fac38e73e346e \ + # RottenLinks + && git clone --single-branch -b master https://github.com/miraheze/RottenLinks.git $MW_HOME/extensions/RottenLinks \ + && cd $MW_HOME/extensions/RottenLinks \ + && git checkout -q a96e99d0a61a42d59587a67db0720ce245a7ee46 \ + # SandboxLink + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/SandboxLink $MW_HOME/extensions/SandboxLink \ + && cd $MW_HOME/extensions/SandboxLink \ + && git checkout -q 9ab23288a010c3894c59cd5ba3096d93d57c15c5 \ + # SaveSpinner + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/SaveSpinner $MW_HOME/extensions/SaveSpinner \ + && cd $MW_HOME/extensions/SaveSpinner \ + && git checkout -q 1e819e2fff7fad6999bafe71d866c3af50836c42 \ + # SemanticDependencyUpdater (v. 2.0.2) + && git clone --single-branch -b master https://github.com/gesinn-it/SemanticDependencyUpdater $MW_HOME/extensions/SemanticDependencyUpdater \ + && cd $MW_HOME/extensions/SemanticDependencyUpdater \ + && git checkout -q 389e34c4d4249d27b283a8a29c654fb708b8b294 \ + # SemanticDrilldown + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/SemanticDrilldown $MW_HOME/extensions/SemanticDrilldown \ + && cd $MW_HOME/extensions/SemanticDrilldown \ + && git checkout -q e960979ec5a3b1e662b3742cee7e7ef4056f9a46 \ + # SimpleChanges + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/SimpleChanges $MW_HOME/extensions/SimpleChanges \ + && cd $MW_HOME/extensions/SimpleChanges \ + && git checkout -q 5352de89dfaf043f646a44582b26f07822f02be7 \ + # SimpleMathJax + && git clone --single-branch https://github.com/jmnote/SimpleMathJax.git $MW_HOME/extensions/SimpleMathJax \ + && cd $MW_HOME/extensions/SimpleMathJax \ + && git checkout -q 3757e9b1cf235b2e2c62e7d208d52206e185b28e \ + # SkinPerPage + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/SkinPerPage $MW_HOME/extensions/SkinPerPage \ + && cd $MW_HOME/extensions/SkinPerPage \ + && git checkout -q 2793602b37c33aa4c769834feac0b88f385ccef9 \ + # SmiteSpam + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/SmiteSpam $MW_HOME/extensions/SmiteSpam \ + && cd $MW_HOME/extensions/SmiteSpam \ + && git checkout -q 268f212b7e366711d8e7b54c7faf5b750fa014ad \ + # SocialProfile + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/SocialProfile $MW_HOME/extensions/SocialProfile \ + && cd $MW_HOME/extensions/SocialProfile \ + && git checkout -q 74fcf9bead948ec0419eea10800c9331bcc1273e \ + # TemplateStyles + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/TemplateStyles $MW_HOME/extensions/TemplateStyles \ + && cd $MW_HOME/extensions/TemplateStyles \ + && git checkout -q 2a93b56e370ab8b8e020ed29c507104b56f1d11a \ + # TemplateWizard + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/TemplateWizard $MW_HOME/extensions/TemplateWizard \ + && cd $MW_HOME/extensions/TemplateWizard \ + && git checkout -q d486e3475f84118fd9b5c77d60254daa2f56f654 \ + # Thanks + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Thanks $MW_HOME/extensions/Thanks \ + && cd $MW_HOME/extensions/Thanks \ + && git checkout -q 03b6a52f263604c819e69b78c157f6ef5adb053e \ + # TimedMediaHandler + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/TimedMediaHandler $MW_HOME/extensions/TimedMediaHandler \ + && cd $MW_HOME/extensions/TimedMediaHandler \ + && git checkout -q 2e64302c68e58693650e91b7869fa5aecf1aaf23 \ + # TinyMCE + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/TinyMCE $MW_HOME/extensions/TinyMCE \ + && cd $MW_HOME/extensions/TinyMCE \ + && git checkout -q 06436ec3a53c6cd53c458e4e8ab3ec8d1a23029b \ + # TitleIcon + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/TitleIcon $MW_HOME/extensions/TitleIcon \ + && cd $MW_HOME/extensions/TitleIcon \ + && git checkout -q 7c6c83f4859642542393612ad961a258378e0cac \ + # UniversalLanguageSelector + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/UniversalLanguageSelector $MW_HOME/extensions/UniversalLanguageSelector \ + && cd $MW_HOME/extensions/UniversalLanguageSelector \ + && git checkout -q 8216e434c38ddeba74e5ad758bfbbcc83861fa60 \ + # UploadWizard + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/UploadWizard $MW_HOME/extensions/UploadWizard \ + && cd $MW_HOME/extensions/UploadWizard \ + && git checkout -q 847413694b519c76da7196023651c8d584137d2f \ + # UrlGetParameters + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/UrlGetParameters $MW_HOME/extensions/UrlGetParameters \ + && cd $MW_HOME/extensions/UrlGetParameters \ + && git checkout -q d36f92810c762b301035ff1b4f42792ed9a1018b \ + # UserFunctions + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/UserFunctions $MW_HOME/extensions/UserFunctions \ + && cd $MW_HOME/extensions/UserFunctions \ + && git checkout -q b532b1047080c3738327ee2f3b541e563e06ca19 \ + # UserMerge + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/UserMerge $MW_HOME/extensions/UserMerge \ + && cd $MW_HOME/extensions/UserMerge \ + && git checkout -q 183bb7a8f78cbe365bec0fbd4b3ecdd4fae1a359 \ + # UserPageViewTracker (v. 0.7) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/UserPageViewTracker $MW_HOME/extensions/UserPageViewTracker \ + && cd $MW_HOME/extensions/UserPageViewTracker \ + && git checkout -q f4b7c20c372165541164d449c12df1e74e98ed0b \ + # Variables + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Variables $MW_HOME/extensions/Variables \ + && cd $MW_HOME/extensions/Variables \ + && git checkout -q b4a9063f16a928567e3b6788cda9246c2e94797f \ + # VEForAll (v. 0.4.1) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/VEForAll $MW_HOME/extensions/VEForAll \ + && cd $MW_HOME/extensions/VEForAll \ + && git checkout -q 2f1f08eca7fbf61198e5f4ccf2d627a6c9ef7b64 \ + # VoteNY + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/VoteNY $MW_HOME/extensions/VoteNY \ + && cd $MW_HOME/extensions/VoteNY \ + && git checkout -q 11c103f4b9167a8d8d5e850d8a781c6f49b249c1 \ + # WatchAnalytics (v. 3.2.0) + && git clone --single-branch -b master https://gerrit.wikimedia.org/r/mediawiki/extensions/WatchAnalytics $MW_HOME/extensions/WatchAnalytics \ + && cd $MW_HOME/extensions/WatchAnalytics \ + && git checkout -q f6e4d07a93baf502358ce0af01c0ac7e59cc6f4b \ + # WhoIsWatching + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/WhoIsWatching $MW_HOME/extensions/WhoIsWatching \ + && cd $MW_HOME/extensions/WhoIsWatching \ + && git checkout -q 836a31018e26ab7c993088c4cca31a89efec2ee5 \ + # WhosOnline + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/WhosOnline $MW_HOME/extensions/WhosOnline \ + && cd $MW_HOME/extensions/WhosOnline \ + && git checkout -q bb1765d2eb5c88ca10dc8a0be19f35fcffdccdae \ + # Widgets + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/Widgets $MW_HOME/extensions/Widgets \ + && cd $MW_HOME/extensions/Widgets \ + && git checkout -q 197d429f971b2aebbce29b7a91a194e1f8181e64 \ + # WikiForum + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/WikiForum $MW_HOME/extensions/WikiForum \ + && cd $MW_HOME/extensions/WikiForum \ + && git checkout -q a2685b60af86890f199a5f3b6581918369e6a571 \ + # WikiSEO + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/WikiSEO $MW_HOME/extensions/WikiSEO \ + && cd $MW_HOME/extensions/WikiSEO \ + && git checkout -q 610cffa3345333b53d4dda7b55b2012fbfcee9de \ + # WSOAuth + && git clone --single-branch -b $MW_VERSION https://gerrit.wikimedia.org/r/mediawiki/extensions/WSOAuth $MW_HOME/extensions/WSOAuth \ + && cd $MW_HOME/extensions/WSOAuth \ + && git checkout -q 3c54c4899dd63989bc3214273bf1c5807c7ac5db + +# Patch composer +RUN set -x; \ + sed -i 's="monolog/monolog": "2.2.0",="monolog/monolog": "^2.2",=g' $MW_HOME/composer.json + +# Composer dependencies +COPY _sources/configs/composer.canasta.json $MW_HOME/composer.local.json +RUN set -x; \ + cd $MW_HOME \ + && composer update --no-dev \ + # We need the 2nd update for SMW dependencies + && composer update --no-dev \ + # Fix up future use of canasta-extensions directory for composer autoload + && sed -i 's/extensions/canasta-extensions/g' $MW_HOME/vendor/composer/autoload_static.php \ + && sed -i 's/extensions/canasta-extensions/g' $MW_HOME/vendor/composer/autoload_files.php \ + && sed -i 's/extensions/canasta-extensions/g' $MW_HOME/vendor/composer/autoload_classmap.php \ + && sed -i 's/extensions/canasta-extensions/g' $MW_HOME/vendor/composer/autoload_psr4.php \ + && sed -i 's/skins/canasta-skins/g' $MW_HOME/vendor/composer/autoload_static.php \ + && sed -i 's/skins/canasta-skins/g' $MW_HOME/vendor/composer/autoload_files.php \ + && sed -i 's/skins/canasta-skins/g' $MW_HOME/vendor/composer/autoload_classmap.php \ + && sed -i 's/skins/canasta-skins/g' $MW_HOME/vendor/composer/autoload_psr4.php + +# Patches + +# Add Bootstrap to LocalSettings.php if the web installer added the Chameleon skin +COPY _sources/patches/core-local-settings-generator.patch /tmp/core-local-settings-generator.patch +RUN set -x; \ + cd $MW_HOME \ + && git apply /tmp/core-local-settings-generator.patch + +# Cleanup all .git leftovers +RUN set -x; \ + cd $MW_HOME \ + && find . \( -name ".git" -o -name ".gitignore" -o -name ".gitmodules" -o -name ".gitattributes" \) -exec rm -rf -- {} + + +# Generate list of installed extensions +RUN set -x; \ + cd $MW_HOME/extensions \ + && for i in $(ls -d */); do echo "#cfLoadExtension('${i%%/}');"; done > $MW_ORIGIN_FILES/installedExtensions.txt \ + # Dirty hack for SemanticMediawiki + && sed -i "s/#cfLoadExtension('SemanticMediaWiki');/#enableSemantics('localhost');/g" $MW_ORIGIN_FILES/installedExtensions.txt \ + && cd $MW_HOME/skins \ + && for i in $(ls -d */); do echo "#cfLoadSkin('${i%%/}');"; done > $MW_ORIGIN_FILES/installedSkins.txt \ + #Loads Vector skin by default in the LocalSettings.php + && sed -i "s/#cfLoadSkin('Vector');/cfLoadSkin('Vector');/" $MW_ORIGIN_FILES/installedSkins.txt + +# Move files around +RUN set -x; \ + # Move files to $MW_ORIGIN_FILES directory + mv $MW_HOME/images $MW_ORIGIN_FILES/ \ + && mv $MW_HOME/cache $MW_ORIGIN_FILES/ \ + # Move extensions and skins to prefixed directories not intended to be volumed in + && mv $MW_HOME/extensions $MW_HOME/canasta-extensions \ + && mv $MW_HOME/skins $MW_HOME/canasta-skins \ + # Permissions + && chown $WWW_USER:$WWW_GROUP -R $MW_HOME/canasta-extensions \ + && chmod g+w -R $MW_HOME/canasta-extensions \ + && chown $WWW_USER:$WWW_GROUP -R $MW_HOME/canasta-skins \ + && chmod g+w -R $MW_HOME/canasta-skins \ + # Create symlinks from $MW_VOLUME to the wiki root for images and cache directories + && ln -s $MW_VOLUME/images $MW_HOME/images \ + && ln -s $MW_VOLUME/cache $MW_HOME/cache + +# Create place where extensions and skins symlinks will live +RUN set -x; \ + mkdir $MW_HOME/extensions/ \ + && mkdir $MW_HOME/skins/ + +FROM base as final + +COPY --from=source $MW_HOME $MW_HOME +COPY --from=source $MW_ORIGIN_FILES $MW_ORIGIN_FILES + +# Default values +ENV MW_ENABLE_JOB_RUNNER=true \ + MW_JOB_RUNNER_PAUSE=2 \ + MW_ENABLE_TRANSCODER=true \ + MW_JOB_TRANSCODER_PAUSE=60 \ + MW_MAP_DOMAIN_TO_DOCKER_GATEWAY=true \ + MW_ENABLE_SITEMAP_GENERATOR=false \ + MW_SITEMAP_PAUSE_DAYS=1 \ + MW_SITEMAP_SUBDIR="" \ + MW_SITEMAP_IDENTIFIER="mediawiki" \ + PHP_UPLOAD_MAX_FILESIZE=10M \ + PHP_POST_MAX_SIZE=10M \ + PHP_MAX_INPUT_VARS=1000 \ + PHP_MAX_EXECUTION_TIME=60 \ + PHP_MAX_INPUT_TIME=60 \ + LOG_FILES_COMPRESS_DELAY=3600 \ + LOG_FILES_REMOVE_OLDER_THAN_DAYS=10 + +COPY _sources/configs/msmtprc /etc/ +COPY _sources/configs/php_error_reporting.ini _sources/configs/php_upload_max_filesize.ini /etc/php/7.4/cli/conf.d/ +COPY _sources/configs/php_error_reporting.ini _sources/configs/php_upload_max_filesize.ini /etc/php/7.4/fpm/conf.d/ +COPY _sources/scripts/*.sh / +COPY _sources/scripts/*.php $MW_HOME/maintenance/ +COPY _sources/configs/robots.txt $WWW_ROOT/ +COPY _sources/configs/.htaccess $WWW_ROOT/ +COPY _sources/images/favicon.ico $WWW_ROOT/ +COPY _sources/canasta/LocalSettings.php _sources/canasta/CanastaUtils.php _sources/canasta/CanastaDefaultSettings.php $MW_HOME/ +COPY _sources/canasta/getMediawikiSettings.php / + +RUN set -x; \ + chmod -v +x /*.sh \ + # Sitemap directory + && ln -s $MW_VOLUME/sitemap $MW_HOME/sitemap \ + # Make web installer work with Canasta + && cp "$MW_HOME/includes/NoLocalSettings.php" "$MW_HOME/includes/CanastaNoLocalSettings.php" \ + && sed -i 's/MW_CONFIG_FILE/CANASTA_CONFIG_FILE/g' "$MW_HOME/includes/CanastaNoLocalSettings.php" \ + # Enable environment variables for FPM workers + && sed -i '/clear_env/s/^;//' /etc/php/7.4/fpm/pool.d/www.conf + +COPY _sources/images/Powered-by-Canasta.png /var/www/mediawiki/w/resources/assets/ + +EXPOSE 80 +WORKDIR $MW_HOME + +HEALTHCHECK --interval=1m --timeout=10s \ + CMD wget -q --method=HEAD localhost/w/api.php + +CMD ["/run-apache.sh"] diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..d868c3a --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,11 @@ +Canasta version history: + +- 1.0.0 - April 14, 2022 - initial version +- 1.0.1 - April 14, 2022 - update MediaWiki version to 1.35.6 +- 1.1.0 - April 29, 2022 - rename /user-extensions and /user-skins directories to /extensions and /skins +- 1.1.1 - June 16, 2022 - Disable sitemap generator by default; update CommentStreams extension; remove Favorites and MobileDetect extensions; add iputils-ping package +- 1.1.2 - July 12, 2022 - update MediaWiki version to 1.35.7; add default setting of $wgServer; add CookieWarning extension; update CommentStreams, Echo and EmbedVideo extensions; remove HeadScript extension; add poppler-utils package for PDF rendering +- 1.2.0 - October 2, 2022 - update MediaWiki version to 1.35.8; remove cfLoadExtension() and cfLoadSkin() functionality in favor of symlink-based approach; add displayWikiInfo.php script; make use of gateway.docker.internal to detect host address +- 1.2.1 - November 25, 2022 - add AArch64 support; update SimpleBatchUpload extension +- 1.2.2 - December 22, 2022 - Fix installation of EmailAuthorization extension; fix web installer to also install Boostrap extension if Chameleon skin gets installed; add MW_MAP_DOMAIN_TO_DOCKER_GATEWAY as an environment variable (set to true by default); remove patches made unnecessary by cfLoad... removal +- 1.3.0 - February 17, 2023 - update MediaWiki version to 1.39.0; update all extensions to a compatible version (in most cases, using the REL1_39 Git branch); add the extensions AbuseFilter, DeleteBatch, MediaUploader, Mermaid, SemanticDependencyUpdater, TemplateWizard, Title Icon, UserPageViewTracker, WatchAnalytics, WhosOnline; remove the extensions DiscussionTools, LocalisationUpdate; add the skin Vector 2022; add header warning to email-related special pages if $wgSMTP is not set diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..589268e --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.3.0 \ No newline at end of file diff --git a/_sources/canasta/CanastaDefaultSettings.php b/_sources/canasta/CanastaDefaultSettings.php new file mode 100644 index 0000000..3ea1ed7 --- /dev/null +++ b/_sources/canasta/CanastaDefaultSettings.php @@ -0,0 +1,78 @@ + $k ) { + unset( $$k ); + } + unset( $vars, $v, $k ); + return; + } +} +// WebStart entry point + +// Check that user's LocalSettings.php exists +if ( !is_readable( $canastaLocalSettingsFilePath ) ) { + // Emulate that "$IP/LocalSettings.php" does not exist + + // Set CANASTA_CONFIG_FILE for NoLocalSettings template work correctly in includes/CanastaNoLocalSettings.php + define( "CANASTA_CONFIG_FILE", $canastaLocalSettingsFilePath ); + + // Do the same what function wfWebStartNoLocalSettings() does + require_once "$IP/includes/CanastaNoLocalSettings.php"; + die(); +} + +// Canasta default settings below + +$wgServer = getenv( 'MW_SITE_SERVER' ) ?? 'http://localhost'; + +## The URL base path to the directory containing the wiki; +## defaults for all runtime URL paths are based off of this. +## For more information on customizing the URLs +## (like /w/index.php/Page_title to /wiki/Page_title) please see: +## https://www.mediawiki.org/wiki/Manual:Short_URL +$wgScriptPath = "/w"; +$wgScriptExtension = ".php"; +$wgArticlePath = '/wiki/$1'; +$wgStylePath = $wgScriptPath . '/skins'; + +## The URL path to static resources (images, scripts, etc.) +$wgResourceBasePath = $wgScriptPath; + +# SyntaxHighlight_GeSHi +$wgPygmentizePath = '/usr/bin/pygmentize'; + +# We use job runner instead +$wgJobRunRate = 0; + +# SVG Converters +$wgSVGConverter = 'rsvg'; + +# Docker specific setup +# see https://www.mediawiki.org/wiki/Manual:$wgCdnServersNoPurge +$wgUseCdn = true; +$wgCdnServersNoPurge = []; +$wgCdnServersNoPurge[] = '172.16.0.0/12'; +$wgCdnServersNoPurge[] = '192.168.0.0/16'; +$wgCdnServersNoPurge[] = '10.0.0.0/8'; + +# Include user defined LocalSettings.php file +require_once "$canastaLocalSettingsFilePath"; + +# Include all php files in config/settings directory +foreach (glob(getenv( 'MW_VOLUME' ) . '/config/settings/*.php') as $filename) { + require_once $filename; +} diff --git a/_sources/canasta/LocalSettings.php b/_sources/canasta/LocalSettings.php new file mode 100644 index 0000000..c126aa9 --- /dev/null +++ b/_sources/canasta/LocalSettings.php @@ -0,0 +1,8 @@ +addOption( + 'variable', + '', + false, + true + ); + $this->addOption( + 'versions', + '', + false, + false + ); + $this->addOption( + 'isSMWValid', + '' + ); + $this->addOption( + 'SMWUpgradeKey', + '' + ); + $this->addOption( + 'SWMIncompleteSetupTasks', + '' + ); + $this->addOption( + 'format', + '', + false, + true + ); + } + + public function execute() { + $return = null; + if ( $this->hasOption( 'variable' ) ) { + $variableName = $this->getOption( 'variable' ); + $config = MediaWikiServices::getInstance()->getMainConfig(); + if ( $config->has( $variableName ) ) { + $return = $config->get( $variableName ); + } else { // the last chance to fetch a value from global variable + $return = $GLOBALS[$variableName] ?? ''; + } + } elseif ( $this->hasOption( 'versions' ) ) { + $return = [ + 'MediaWiki' => SpecialVersion::getVersion( 'nodb' ), + ]; + $extThings = self::getExtensionsThings(); + foreach ( $extThings as $name => $extension ) { + $return[$name] = $extension['version'] ?? ''; + // Try to add git version + if ( isset( $extension['path'] ) ) { + $extensionPath = dirname( $extension['path'] ); + $gitInfo = new GitInfo( $extensionPath ); + $gitVersion = substr( $gitInfo->getHeadSHA1() ?: '', 0, 7 ); + $return[$name] .= " ($gitVersion)"; + } + } + } elseif ( $this->hasOption( 'isSMWValid' ) ) { + $extThings = self::getExtensionsThings(); + if ( isset( $extThings['SemanticMediaWiki'] ) ) { + $this->output( SMW\Setup::isValid() ? 'true' : 'false' ); + } else { + $this->output( 'SMW not installed' ); + } + return; + } elseif ( $this->hasOption( 'SMWUpgradeKey' ) ) { + $extThings = self::getExtensionsThings(); + if ( isset( $extThings['SemanticMediaWiki'] ) ) { + SemanticMediaWiki::onExtensionFunction(); + $smwId = SMW\Site::id(); + $return = $GLOBALS['smw.json'][$smwId]['upgrade_key'] ?? ''; + } + } elseif ( $this->hasOption( 'SWMIncompleteSetupTasks' ) ) { + $extThings = self::getExtensionsThings(); + if ( isset( $extThings['SemanticMediaWiki'] ) ) { + SemanticMediaWiki::onExtensionFunction(); + $SMWSetupFile = new SMW\SetupFile(); + $SMWIncompleteTasks = $SMWSetupFile->findIncompleteTasks(); + $return = $SMWIncompleteTasks; + } + } + + $format = $this->getOption( 'format', 'string' ); + if ( $format === 'md5' ) { + if ( is_array( $return ) ) { + $return = FormatJson::encode( $return ); + } + $this->output( md5( $return ) ); + } elseif ( $format === 'first' ) { + if ( is_array( $return ) ) { + if ( $return ) { + $return = array_values( $return )[0]; + } else { + $return = ''; + } + } + $this->output( $return ); + } elseif ( $format === 'semicolon' ) { + if ( is_array( $return ) ) { + $return = implode( ';', $return ); + } + $this->output( $return ); + } elseif ( $format === 'space' ) { + if ( is_array( $return ) ) { + $return = implode( ' ', $return ); + } + $this->output( $return ); + } elseif ( is_array( $return ) || strcasecmp( $format, 'json' ) === 0 ) { + // return json format by default for an array + $this->output( FormatJson::encode( $return ) ); + } else { // string + $this->output( $return ); + } + } + + public function getDbType() { + return Maintenance::DB_NONE; + } + + /** + * Remove values from the SetupAfterCache hooks at last-minute setup because + * some extensions makes requests to the database using the SetupAfterCache hook + * (for example they can check user and etc..) + * but this script can be used for getting parameters when database is not initialized yet + */ + public function finalSetup() { + parent::finalSetup(); + + global $wgShowExceptionDetails, $wgHooks; + + $wgShowExceptionDetails = true; + $wgHooks['SetupAfterCache'][] = function () { + global $wgExtensionFunctions; + $wgExtensionFunctions = []; + }; + } + + private static function getExtensionsThings() { + $extensionRegistry = ExtensionRegistry::getInstance(); + return $extensionRegistry->getAllThings(); + } +} + +$maintClass = GetMediawikiSettings::class; +require RUN_MAINTENANCE_IF_MAIN; diff --git a/_sources/configs/composer.canasta.json b/_sources/configs/composer.canasta.json new file mode 100644 index 0000000..ecc68dd --- /dev/null +++ b/_sources/configs/composer.canasta.json @@ -0,0 +1,34 @@ +{ + "require": { + "mediawiki/chameleon-skin": "~4.0", + "mediawiki/maps": "10.0.0", + "mediawiki/mermaid": "~3.1", + "mediawiki/semantic-media-wiki": "4.0.2", + "mediawiki/semantic-result-formats": "4.0.1", + "mediawiki/semantic-breadcrumb-links": "2.1.x-dev", + "mediawiki/semantic-compound-queries": "~2.2", + "mediawiki/semantic-extra-special-properties": "3.0.1", + "mediawiki/semantic-scribunto": "2.2.0", + "mediawiki/simple-batch-upload": "1.8.2", + "mediawiki/bootstrap-components": "^5.0", + "mediawiki/sub-page-list": "2.0.2" + }, + "extra": { + "merge-plugin": { + "include": [ + "extensions/AbuseFilter/composer.json", + "extensions/CirrusSearch/composer.json", + "extensions/DataTransfer/composer.json", + "extensions/Elastica/composer.json", + "extensions/OATHAuth/composer.json", + "extensions/TimedMediaHandler/composer.json", + "extensions/AntiSpoof/composer.json", + "extensions/TemplateStyles/composer.json", + "extensions/Widgets/composer.json", + "extensions/GoogleAnalyticsMetrics/composer.json", + "extensions/OpenIDConnect/composer.json", + "extensions/WSOAuth/composer.json" + ] + } + } +} diff --git a/_sources/configs/msmtprc b/_sources/configs/msmtprc new file mode 100644 index 0000000..9305ec1 --- /dev/null +++ b/_sources/configs/msmtprc @@ -0,0 +1,22 @@ +# Example for a system wide configuration file + +# A system wide configuration file is optional. +# If it exists, it usually defines a default account. +# This allows msmtp to be used like /usr/sbin/sendmail. +account default + +# The SMTP smarthost +host DOCKER_GATEWAY + +port 25 +tls off +tls_starttls off + +# Disable automatic envelope-from addresses. The default is off. +auto_from off +#maildomain oursite.example + +# Disable syslog logging, it does not work in docker +syslog off + +logfile /var/log/mediawiki/msmtp.log diff --git a/_sources/configs/php_error_reporting.ini b/_sources/configs/php_error_reporting.ini new file mode 100644 index 0000000..b0d3935 --- /dev/null +++ b/_sources/configs/php_error_reporting.ini @@ -0,0 +1,5 @@ +log_errors=On +; must be an integer, see +; https://www.php.net/manual/en/function.error-reporting +; https://www.php.net/manual/en/errorfunc.constants.php +error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT diff --git a/_sources/configs/php_max_input_vars.ini b/_sources/configs/php_max_input_vars.ini new file mode 100644 index 0000000..90ce3eb --- /dev/null +++ b/_sources/configs/php_max_input_vars.ini @@ -0,0 +1,2 @@ +; Override default PHP settings max_input_vars +max_input_vars="${PHP_MAX_INPUT_VARS}" diff --git a/_sources/configs/php_timeouts.ini b/_sources/configs/php_timeouts.ini new file mode 100644 index 0000000..136b11f --- /dev/null +++ b/_sources/configs/php_timeouts.ini @@ -0,0 +1,2 @@ +max_execution_time="${PHP_MAX_EXECUTION_TIME}" +max_input_time="${PHP_MAX_INPUT_TIME}" diff --git a/_sources/configs/php_upload_max_filesize.ini b/_sources/configs/php_upload_max_filesize.ini new file mode 100644 index 0000000..3006c13 --- /dev/null +++ b/_sources/configs/php_upload_max_filesize.ini @@ -0,0 +1,3 @@ +; Override default PHP settings to allow for uploads larger than 2M +upload_max_filesize="${PHP_UPLOAD_MAX_FILESIZE}" +post_max_size="${PHP_POST_MAX_SIZE}" diff --git a/_sources/extensions/GTag1.2.0.tar.gz b/_sources/extensions/GTag1.2.0.tar.gz new file mode 100644 index 0000000..8b279c8 Binary files /dev/null and b/_sources/extensions/GTag1.2.0.tar.gz differ diff --git a/_sources/images/Powered-by-Canasta.png b/_sources/images/Powered-by-Canasta.png new file mode 100644 index 0000000..a768a60 Binary files /dev/null and b/_sources/images/Powered-by-Canasta.png differ diff --git a/_sources/images/README.md b/_sources/images/README.md new file mode 100644 index 0000000..8b8fc03 --- /dev/null +++ b/_sources/images/README.md @@ -0,0 +1 @@ +Directory for Canasta-specific images. diff --git a/_sources/images/favicon.ico b/_sources/images/favicon.ico new file mode 100644 index 0000000..85a4d9f Binary files /dev/null and b/_sources/images/favicon.ico differ diff --git a/_sources/patches/core-local-settings-generator.patch b/_sources/patches/core-local-settings-generator.patch new file mode 100644 index 0000000..5c81e27 --- /dev/null +++ b/_sources/patches/core-local-settings-generator.patch @@ -0,0 +1,18 @@ +--- a/includes/installer/LocalSettingsGenerator.php ++++ b/includes/installer/LocalSettingsGenerator.php +@@ -51,6 +51,15 @@ + $this->skins = $installer->getVar( '_Skins' ); + $this->IP = $installer->getVar( 'IP' ); + ++ // Patch for Canasta - if the user is enabling the Chameleon ++ // skin (likely, since all skins are selected by default), make ++ // sure the Bootstrap skin is enabled as well, to avoid a ++ // MediaWiki error. ++ if ( in_array( 'chameleon', $this->skins ) && ++ !in_array( 'Bootstrap', $this->extensions ) ) { ++ $this->extensions[] = 'Bootstrap'; ++ } ++ + $db = $installer->getDBInstaller( $installer->getVar( 'wgDBtype' ) ); + + $confItems = array_merge( diff --git a/_sources/scripts/displayWikiInfo.php b/_sources/scripts/displayWikiInfo.php new file mode 100644 index 0000000..e7dc411 --- /dev/null +++ b/_sources/scripts/displayWikiInfo.php @@ -0,0 +1,50 @@ +addDescription( "Displays information relating to this wiki." ); + } + + public function execute() { + global $wgDBname; + + $info = [ 'DB name' => $wgDBname ]; + print json_encode( $info ) . "\n"; + } + +} + +require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/_sources/scripts/mwjobrunner.sh b/_sources/scripts/mwjobrunner.sh new file mode 100755 index 0000000..101b7e6 --- /dev/null +++ b/_sources/scripts/mwjobrunner.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +RJ=$MW_HOME/maintenance/runJobs.php + +echo Starting job runner... +# Wait 10 seconds after the server starts up to give other processes time to get started +sleep 10 +echo Job runner started. +while true; do + # Job types that need to be run ASAP mo matter how many of them are in the queue + # Those jobs should be very "cheap" to run + php $RJ --type="enotifNotify" + sleep 1 + php $RJ --type="createPage" + sleep 1 + php $RJ --type="refreshLinks" + sleep 1 + php $RJ --type="htmlCacheUpdate" --maxjobs=500 + sleep 1 + # Everything else, limit the number of jobs on each batch + # The --wait parameter will pause the execution here until new jobs are added, + # to avoid running the loop without anything to do + php $RJ --maxjobs=10 + + # Wait some seconds to let the CPU do other things, like handling web requests, etc + echo mwjobrunner waits for "$MW_JOB_RUNNER_PAUSE" seconds... + sleep "$MW_JOB_RUNNER_PAUSE" +done diff --git a/_sources/scripts/mwsitemapgen.sh b/_sources/scripts/mwsitemapgen.sh new file mode 100755 index 0000000..61e4baf --- /dev/null +++ b/_sources/scripts/mwsitemapgen.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +SCRIPT=$MW_HOME/maintenance/generateSitemap.php +# Verify the delay is >= 1, otherwise fall back to 1 +if [ "$MW_SITEMAP_PAUSE_DAYS" -lt "1" ]; then + MW_SITEMAP_PAUSE_DAYS=1 +fi +# Convert to seconds (suffixed sleep command has issues on OSX) +SLEEPDAYS=$(expr $MW_SITEMAP_PAUSE_DAYS \* 60 \* 60 \* 24) + +SITE_SERVER=$MW_SITE_SERVER +# Fallback to https:// scheme if it's protocol-relative +if [[ $SITE_SERVER == "//"* ]]; then + SITE_SERVER="https:$SITE_SERVER" +fi + +# Adds slash to sitemap dir if it's not empty and has no starting slash +SITEMAP_DIR=$MW_SITEMAP_SUBDIR +if [[ -n "$SITEMAP_DIR" && "$SITEMAP_DIR" != "/"* ]]; then + SITEMAP_DIR="/$SITEMAP_DIR" +fi + +GOOGLE_PING_URL="https://www.google.com/ping?sitemap=${SITE_SERVER}${MW_SCRIPT_PATH}/sitemap${SITEMAP_DIR}/sitemap-index-${MW_SITEMAP_IDENTIFIER}.xml" + +echo Starting sitemap generator... +# Wait three minutes after the server starts up to give other processes time to get started +sleep 30 +echo Sitemap generator started. +while true; do + php $SCRIPT \ + --fspath=$MW_HOME/sitemap/$MW_SITEMAP_SUBDIR \ + --urlpath=$MW_SCRIPT_PATH/sitemap/$MW_SITEMAP_SUBDIR \ + --compress yes \ + --server=$MW_SITE_SERVER \ + --skip-redirects \ + --identifier=$MW_SITEMAP_IDENTIFIER + + # sending the sitemap to google + echo "sending to Google -> $GOOGLE_PING_URL" + curl --silent "$GOOGLE_PING_URL" > /dev/null + + # Wait some seconds to let the CPU do other things, like handling web requests, etc + echo mwsitemapgen waits for "$SLEEPDAYS" seconds... + sleep "$SLEEPDAYS" +done diff --git a/_sources/scripts/mwtranscoder.sh b/_sources/scripts/mwtranscoder.sh new file mode 100755 index 0000000..50ca211 --- /dev/null +++ b/_sources/scripts/mwtranscoder.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +RJ=$MW_HOME/maintenance/runJobs.php +echo Starting transcoder... +# Wait three minutes after the server starts up to give other processes time to get started +sleep 180 +echo Transcoder started. +while true; do + php $RJ --type webVideoTranscodePrioritized --maxjobs=10 + sleep 1 + php $RJ --type webVideoTranscode --maxjobs=1 + + # Wait some seconds to let the CPU do other things, like handling web requests, etc + echo mwtranscoder waits for "$MW_JOB_TRANSCODER_PAUSE" seconds... + sleep "$MW_JOB_TRANSCODER_PAUSE" +done diff --git a/_sources/scripts/run-apache.sh b/_sources/scripts/run-apache.sh new file mode 100755 index 0000000..dc2149a --- /dev/null +++ b/_sources/scripts/run-apache.sh @@ -0,0 +1,227 @@ +#!/bin/bash + +set -x + +# read variables from LocalSettings.php +get_mediawiki_variable () { + php /getMediawikiSettings.php --variable="$1" --format="${2:-string}" +} + +isTrue() { + case $1 in + "True" | "TRUE" | "true" | 1) + return 0 + ;; + *) + return 1 + ;; + esac +} + +isFalse() { + case $1 in + "True" | "TRUE" | "true" | 1) + return 1 + ;; + *) + return 0 + ;; + esac +} + +dir_is_writable() { + # Use -L to get information about the target of a symlink, + # not the link itself, as pointed out in the comments + INFO=( $(stat -L -c "0%a %G %U" "$1") ) + PERM=${INFO[0]} + GROUP=${INFO[1]} + OWNER=${INFO[2]} + + if (( ($PERM & 0002) != 0 )); then + # Everyone has write access + return 0 + elif (( ($PERM & 0020) != 0 )); then + # Some group has write access. + # Is user in that group? + if [[ $GROUP == $WWW_GROUP ]]; then + return 0 + fi + elif (( ($PERM & 0200) != 0 )); then + # The owner has write access. + # Does the user own the file? + [[ $WWW_USER == $OWNER ]] && return 0 + fi + + return 1 +} + +prepare_extensions_skins_symlinks() { + echo "Symlinking bundled extensions..." + for bundled_extension_path in $(find $MW_HOME/canasta-extensions/ -maxdepth 1 -mindepth 1 -type d) + do + bundled_extension_id=$(basename $bundled_extension_path) + ln -s $MW_HOME/canasta-extensions/$bundled_extension_id/ $MW_HOME/extensions/$bundled_extension_id + done + echo "Symlinking bundled skins..." + for bundled_skin_path in $(find $MW_HOME/canasta-skins/ -maxdepth 1 -mindepth 1 -type d) + do + bundled_skin_id=$(basename $bundled_skin_path) + ln -s $MW_HOME/canasta-skins/$bundled_skin_id/ $MW_HOME/skins/$bundled_skin_id + done + echo "Symlinking user extensions and overwriting any redundant bundled extensions..." + for user_extension_path in $(find $MW_HOME/user-extensions/ -maxdepth 1 -mindepth 1 -type d) + do + user_extension_id=$(basename $user_extension_path) + extension_symlink_path="$MW_HOME/extensions/$user_extension_id" + if [[ -e "$extension_symlink_path" ]] + then + rm "$extension_symlink_path" + fi + ln -s $MW_HOME/user-extensions/$user_extension_id/ $MW_HOME/extensions/$user_extension_id + done + echo "Symlinking user skins and overwriting any redundant bundled skins..." + for user_skin_path in $(find $MW_HOME/user-skins/ -maxdepth 1 -mindepth 1 -type d) + do + user_skin_id=$(basename $user_skin_path) + skin_symlink_path="$MW_HOME/skins/$user_skin_id" + if [[ -e "$skin_symlink_path" ]] + then + rm "$skin_symlink_path" + fi + ln -s $MW_HOME/user-skins/$user_skin_id/ $MW_HOME/skins/$user_skin_id + done +} + +# Symlink all extensions and skins (both bundled and user) +prepare_extensions_skins_symlinks + +# Soft sync contents from $MW_ORIGIN_FILES directory to $MW_VOLUME +# The goal of this operation is to copy over all the files generated +# by the image to bind-mount points on host which are bind to +# $MW_VOLUME (./extensions, ./skins, ./config, ./images), +# note that this command will also set all the necessary permissions +echo "Syncing files..." +rsync -ah --inplace --ignore-existing --remove-source-files \ + -og --chown=$WWW_USER:$WWW_GROUP --chmod=Fg=rw,Dg=rwx \ + "$MW_ORIGIN_FILES"/ "$MW_VOLUME"/ + +# We don't need it anymore +rm -rf "$MW_ORIGIN_FILES" + +/update-docker-gateway.sh + +# Permissions +# Note: this part if checking for root directories permissions +# assuming that if the root directory has correct permissions set +# it's in result of previous success run of this code or this code +# was executed by another container (in case mount points are shared) +# hence it does not perform any recursive checks and may lead to files +# or directories down the tree having incorrect permissions left untouched + +echo "Checking permissions of $MW_VOLUME..." +if dir_is_writable $MW_VOLUME; then + echo "Permissions are OK!" +else + chown -R "$WWW_USER":"$WWW_GROUP" "$MW_VOLUME" + chmod -R g=rwX "$MW_VOLUME" +fi + + +jobrunner() { + sleep 3 + if isTrue "$MW_ENABLE_JOB_RUNNER"; then + echo >&2 Run Jobs + nice -n 20 runuser -c /mwjobrunner.sh -s /bin/bash "$WWW_USER" + else + echo >&2 Job runner is disabled + fi +} + +transcoder() { + sleep 3 + if isTrue "$MW_ENABLE_TRANSCODER"; then + echo >&2 Run transcoder + nice -n 20 runuser -c /mwtranscoder.sh -s /bin/bash "$WWW_USER" + else + echo >&2 Transcoder disabled + fi +} + +sitemapgen() { + sleep 3 + if isTrue "$MW_ENABLE_SITEMAP_GENERATOR"; then + echo "Checking permissions of $MW_VOLUME/sitemap" + if dir_is_writable $MW_VOLUME/sitemap; then + echo "Permissions are OK!" + else + chown -R "$WWW_USER":"$WWW_GROUP" "$MW_VOLUME/sitemap" + chmod -R g=rwX "$MW_VOLUME/sitemap" + fi + # Fetch & export script path for sitemap generator + if [ -z "$MW_SCRIPT_PATH" ]; then + MW_SCRIPT_PATH=$(get_mediawiki_variable wgScriptPath) + fi + # Fall back to default value if can't fetch the variable + if [ -z "$MW_SCRIPT_PATH" ]; then + MW_SCRIPT_PATH="/w" + fi + echo >&2 Run sitemap generator + MW_SCRIPT_PATH=$MW_SCRIPT_PATH nice -n 20 runuser -c /mwsitemapgen.sh -s /bin/bash "$WWW_USER" + else + echo >&2 Sitemap generator is disabled + fi +} + +waitdatabase() { + if isFalse "$USE_EXTERNAL_DB"; then + /wait-for-it.sh -t 60 db:3306 + fi +} + +#waitelastic() { +# ./wait-for-it.sh -t 60 elasticsearch:9200 +#} + +run_autoupdate () { + echo "Running auto-update..." + runuser -c "php maintenance/update.php --quick" -s /bin/bash "$WWW_USER" + echo "Auto-update completed" +} + +check_mount_points () { + # Check for $MW_HOME/user-extensions presence and bow out if it's not in place + if [ ! -d "$MW_HOME/user-extensions" ]; then + echo "WARNING! As of Canasta 1.2.0, $MW_HOME/user-extensions is the correct mount point! Please update your Docker Compose stack to 1.2.0, which will re-mount to $MW_HOME/user-extensions." + exit 1 + fi + + # Check for $MW_HOME/user-skins presence and bow out if it's not in place + if [ ! -d "$MW_HOME/user-skins" ]; then + echo "WARNING! As of Canasta 1.2.0, $MW_HOME/user-skins is the correct mount point! Please update your Docker Compose stack to 1.2.0, which will re-mount to $MW_HOME/user-skins." + exit 1 + fi +} + +# Wait db +waitdatabase + +# Check for `user-` prefixed mounts and bow out if not found +check_mount_points + +sleep 1 +cd "$MW_HOME" || exit + +########## Run maintenance scripts ########## +echo "Checking for LocalSettings..." +if [ -e "$MW_VOLUME/config/LocalSettings.php" ]; then + # Run auto-update + run_autoupdate +fi + +echo "Starting services..." +jobrunner & +transcoder & +sitemapgen & + +# waiting for maintainenece scripts +wait \ No newline at end of file diff --git a/_sources/scripts/update-docker-gateway.sh b/_sources/scripts/update-docker-gateway.sh new file mode 100644 index 0000000..b44d203 --- /dev/null +++ b/_sources/scripts/update-docker-gateway.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +set -x + +# read variables from LocalSettings.php +get_mediawiki_variable () { + php /getMediawikiSettings.php --variable="$1" --format="${2:-string}" +} + +get_docker_gateway () { + getent hosts "gateway.docker.internal" | awk '{ print $1 }' +} + +isTrue() { + case $1 in + "True" | "TRUE" | "true" | 1) + return 0 + ;; + *) + return 1 + ;; + esac +} + +# Try to fetch gateway IP from extra host +DOCKER_GATEWAY=$(get_docker_gateway) + +# Fall back to default 172.x network if unable to fetch gateway +if [ -z "$DOCKER_GATEWAY" ]; then + DOCKER_GATEWAY="172.17.0.1" +fi + +WG_SITE_SERVER=$(get_mediawiki_variable wgServer) + +# Map host for VisualEditor +cp /etc/hosts ~/hosts.new +sed -i '/# MW_SITE_HOST/d' ~/hosts.new +if [ -n "$WG_SITE_SERVER" ]; then + MW_SITE_HOST=$(echo "$WG_SITE_SERVER" | sed -e 's|^[^/]*//||' -e 's|[:/].*$||') + if ! isTrue "$MW_MAP_DOMAIN_TO_DOCKER_GATEWAY"; then + echo "MW_MAP_DOMAIN_TO_DOCKER_GATEWAY is not true" + elif [[ $MW_SITE_HOST =~ ^[0-9]+.[0-9]+.[0-9]+.[0-9]+$ ]]; then + echo "MW_SITE_HOST is IP address '$MW_SITE_HOST'" + else + echo "Add MW_SITE_HOST '$DOCKER_GATEWAY $MW_SITE_HOST' to /etc/hosts" + echo "$DOCKER_GATEWAY $MW_SITE_HOST # MW_SITE_HOST" >> ~/hosts.new + fi +fi +cp -f ~/hosts.new /etc/hosts + +# Update /etc/ssmtp/ssmtp.conf to use DOCKER_GATEWAY +sed -i "s/DOCKER_GATEWAY/$DOCKER_GATEWAY/" /etc/msmtprc diff --git a/_sources/scripts/wait-for-it.sh b/_sources/scripts/wait-for-it.sh new file mode 100644 index 0000000..d990e0d --- /dev/null +++ b/_sources/scripts/wait-for-it.sh @@ -0,0 +1,182 @@ +#!/usr/bin/env bash +# Use this script to test if a given TCP host/port are available + +WAITFORIT_cmdname=${0##*/} + +echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + else + echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" + fi + WAITFORIT_start_ts=$(date +%s) + while : + do + if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then + nc -z $WAITFORIT_HOST $WAITFORIT_PORT + WAITFORIT_result=$? + else + (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 + WAITFORIT_result=$? + fi + if [[ $WAITFORIT_result -eq 0 ]]; then + WAITFORIT_end_ts=$(date +%s) + echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" + break + fi + sleep 1 + done + return $WAITFORIT_result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $WAITFORIT_QUIET -eq 1 ]]; then + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + else + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + fi + WAITFORIT_PID=$! + trap "kill -INT -$WAITFORIT_PID" INT + wait $WAITFORIT_PID + WAITFORIT_RESULT=$? + if [[ $WAITFORIT_RESULT -ne 0 ]]; then + echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + fi + return $WAITFORIT_RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + WAITFORIT_hostport=(${1//:/ }) + WAITFORIT_HOST=${WAITFORIT_hostport[0]} + WAITFORIT_PORT=${WAITFORIT_hostport[1]} + shift 1 + ;; + --child) + WAITFORIT_CHILD=1 + shift 1 + ;; + -q | --quiet) + WAITFORIT_QUIET=1 + shift 1 + ;; + -s | --strict) + WAITFORIT_STRICT=1 + shift 1 + ;; + -h) + WAITFORIT_HOST="$2" + if [[ $WAITFORIT_HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + WAITFORIT_HOST="${1#*=}" + shift 1 + ;; + -p) + WAITFORIT_PORT="$2" + if [[ $WAITFORIT_PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + WAITFORIT_PORT="${1#*=}" + shift 1 + ;; + -t) + WAITFORIT_TIMEOUT="$2" + if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + WAITFORIT_TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + WAITFORIT_CLI=("$@") + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} +WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} +WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} +WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} + +# Check to see if timeout is from busybox? +WAITFORIT_TIMEOUT_PATH=$(type -p timeout) +WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) + +WAITFORIT_BUSYTIMEFLAG="" +if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then + WAITFORIT_ISBUSY=1 + # Check if busybox timeout uses -t flag + # (recent Alpine versions don't support -t anymore) + if timeout &>/dev/stdout | grep -q -e '-t '; then + WAITFORIT_BUSYTIMEFLAG="-t" + fi +else + WAITFORIT_ISBUSY=0 +fi + +if [[ $WAITFORIT_CHILD -gt 0 ]]; then + wait_for + WAITFORIT_RESULT=$? + exit $WAITFORIT_RESULT +else + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + wait_for_wrapper + WAITFORIT_RESULT=$? + else + wait_for + WAITFORIT_RESULT=$? + fi +fi + +if [[ $WAITFORIT_CLI != "" ]]; then + if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then + echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" + exit $WAITFORIT_RESULT + fi + exec "${WAITFORIT_CLI[@]}" +else + exit $WAITFORIT_RESULT +fi diff --git a/hadolint.yaml b/hadolint.yaml new file mode 100644 index 0000000..2a02477 --- /dev/null +++ b/hadolint.yaml @@ -0,0 +1,10 @@ +failure-threshold: error +format: tty +no-color: true +ignored: + - DL3031 + - DL3003 + - SC2086 + - SC2039 + - DL3033 + - DL4006 diff --git a/images/.gitignore b/images/.gitignore new file mode 100644 index 0000000..5e7d273 --- /dev/null +++ b/images/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore