Skip to content

An ansible role for downloading mediawiki into specified directory, installing recommended system packages and downloading additional extensions and skins.

License

Notifications You must be signed in to change notification settings

JonasPammer/ansible-role-mediawiki

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ansible-role-mediawiki

Version on Galaxy Testing CI

An Ansible role for

  • downloading mediawiki into a specified directory,

  • installing recommended system packages

  • downloading additional extensions and skins through Git or Composer

This role does not install/configure an SQL-Server.

This role does not install/configure a Webserver.

This role does not generate a LocalSettings.php (yet).

This role does not execute any of Mediawiki’s maintenance scripts (like update.php which you’ll want to run for most extensions to work) yet.

This role does try to ensure permissions of Mediawiki’s files.

🔎 Metadata

Below you can find information on…

  • the role’s required Ansible version

  • the role’s supported platforms

  • the role’s role dependencies

---
galaxy_info:
  role_name: "mediawiki"
  description:
    "An ansible role for downloading mediawiki into specified directory,
    installing recommended system packages and downloading additional extensions and skins."

  author: "jonaspammer"
  license: "MIT"

  min_ansible_version: "2.11"
  platforms:
    # note: text after "actively tested: " represent the docker image name
    - name: Debian
      versions:
        - bullseye # actively tested: debian11
        - bookworm # actively tested: debian12
    - name: Ubuntu
      versions:
        - focal # actively tested: ubuntu2004
        - jammy # actively tested: ubuntu2204

  galaxy_tags: []

dependencies: []

📌 Requirements

The Ansible User needs to be able to become.

The community.general collection must be installed on the Ansible controller.

composer needs to be installed on the Host in order for the extension downloading functionality to work (even when only using roles sourced from git only).

git needs to be installed on the Host in order for the extension downloading functionality to work.

unzip is recommended to be installed in order for composer to correctly unzip downloaded packets.

📜 Role Variables

# php_version: "7.2"

Required to be set by yourself. Used in the names of the installed PHP Packages. Variable-Name comes from the php-versions role.

Note
Keep in mind that the php version satisfies MediaWiki’s Compatibility Matrix.
Tip
This variable name intentionally overlaps with ansible-role-php-versions. It’s recommended to have it be set in your host_vars specification, because if you accidentally install even just one php package using an alternating version specifier it can mess up your entire system (PHP system packages are weird).
Warning
Leaving this blank will result in the installation of the symlink-packages of the system.
mediawiki_version_major: 1
mediawiki_version_minor: 39
mediawiki_version_release: 0

Version of Mediawiki to download. See releases.wikimedia.org and Wikipedia: MediaWiki Version History.

mediawiki_destination: [default htdocs of distro]/mediawiki

Folder in which to extract the downloaded mediawiki archive into. Must not end with an "/".

The default points to a directory named mediawiki in the default httpd' directory of the distribution:

  • default: /var/www/html

  • Alpine: /var/www/{{ httpd_servername | default(ansible_fqdn) }}

  • Suse: /srv/www/htdocs

mediawiki_destination_permissions: u=rwx,g=rx,o=rx

The permissions the resulting directory should have.

mediawiki_linux_username: ~
mediawiki_linux_group: ~

User and Group that should own the destination directory itself.

Note
You will need to ensure these are created beforehand (e.g. using pre_tasks) - the machine’s passwd configuration is no business to this role.
mediawiki_enable_webserver: true

Enable/Disable this role’s restart httpd handler.

Downloading Extensions

Tip
This can be skipped by skipping the tag mediawiki::extensions.
Tip

By using this role in combination with this variable and its structure you could have something like this in your LocalSettings.php Template:

{% for category_identfier, extensions_array in mediawiki_extensions.items() %}
# {{ category_identfier }} extensions
{%  for extension in extensions_array %}
{%      if extension.load %}
wfLoadExtension("{{ extension.name }}");
{%      endif %}
{%  endfor %}
{% endfor %}
mediawiki_extensions:
  unsorted: []

A dictionary of lists of Extensions to download.

The dictionary keys are to attach an arbitrary "category" to each extension. How you name these "categories" is to your business only.

Each entry of a list may have the following properties (Consult the 📚 Example Playbook Usages-Section for Examples):

name

Name of the Extension as used when registering the extension in LocalSettings.php.

load

Boolean. Can be used in the Jinja2 Template to decide if the extension shall be loaded. Does not have any effect in this role.

gather_type

This variable defines how to gather the extension. Possible values: "composer", "git". Defaults to "git".

Extensions can be gathered for a given MediaWiki-Version through various ways. As of 2021, the most common/supported way is by…

  • Downloading the extension from Git to the /extensions-directory

  • Optionally running composer install [--no-dev …] in the cloned directory to install its dependencies in its directory (kind-of-like npm install).

    Note

    When you download an extension from MediaWiki’s Extension distributor, this step has already been done beforehand.

A more recent initiative attempts to implement the sole use of Composer to gather Mediawiki’s Extensions (instead of just using it for gathering libraries), for-example by issuing composer require mediawiki/semantic-media-wiki in Mediawiki’s base directory. This is still an actively discussed RFC.

This method can only be done if the extension exists as a "Composer package" of-course.

Note

No-matter which version is used to gather the extension, you’ll still need to issue wfLoadExtension in your "LocalSettings.php"-file.

composer_name

Name of the composer package of the Extension, for example as found on packagist.org.

Note

It’s a good Idea to pass in this value even if you plan to use git as the gather-method, assuming your Extensions exists as a composer package. By doing so, this role can make sure Mediawiki’s Composer does not contain this Composer Package (which could cause the weirdest conflicts).

Also, if you do this, I like to explicitly specify the gather_type to be "git" myself.

composer_version

Version Constraint for the Composer Package.

composer_install_pre_config_actions

For each value in this list an appropiate composer config …​ command will be executed prelimentary to the composer <install/require> …​ that follows it.

Each value in this list may either be a string (equals to {arguments: "[insert string]"}) or the following data type:

arguments

literal value passed to community.general.composer’s arguments.

One reason for this variable was the following error message:

        composer/installers contains a Composer plugin which is blocked by your all
        ow-plugins config. You may add it to the list if you consider it safe.
        You can run "composer config --no-plugins allow-plugins.composer/installers
         [true|false]" to enable it (true) or disable it explicitly and suppress th
        is exception (false)
        See https://getcomposer.org/allow-plugins
git_mwrepo_name

If your extensions is under Wikimedias' version control, but uses a different name for their Repository than provided in name, you can use this to supply the name as used in the MediaWiki Repository. Look at the default of git_url to understand this. Defaults to name.

git_url

URL to .git from the repository of the extension. Defaults to https://github.com/wikimedia/mediawiki-extensions-{{ git_mwrepo_name }}.git.

git_version

What version of the repository to check out. This can be the literal string HEAD, a branch name, a tag name. Defaults to REL{{ mediawiki_version_major }}_{{ mediawiki_version_minor }} if not provided.

git_run_composer_install

Boolean or "always". Whether to run composer install in the directory of the Extension. Defaults to value of mediawiki_extensions_git_run_composer_install_default.

  • If set to "always", the command will be executed on every run.

  • If set to a truthy boolean value, the command will be executed if the issued git module reports a change.

system_package_dependencies

Package name(s) to install to the system using ansible.builtin.package.

mediawiki_extensions_git_run_composer_install_default: true

Overwrites the default value for git_run_composer_install of every extension.

Downloading Skins

Tip
This can be skipped by skipping the tag mediawiki::skins.
Tip

By using this role in combination with this variable and its structure you could have something like this in your LocalSettings.php Template:

{% for skin in mediawiki_skins %}
wfLoadSkin( '{{ skin.name }}' );
{% endfor %}
mediawiki_skins: []

A list of Skins to download.

Each entry of the list may have the following properties (Consult the 📚 Example Playbook Usages-Section for Examples):

name

Official Name, as used when loading the skin. If your extensions falls under Wikimedias' version control you will only need to supply this value.

git_url

URL to .git from the repository of the extension. Defaults to https://github.com/wikimedia/mediawiki-extensions-{{ name }}.git if not provided.

git_version

What version of the repository to check out. This can be the literal string HEAD, a branch name, a tag name. Defaults to REL{{ mediawiki_version_major }}_{{ mediawiki_version_minor }} if not provided.

📜 Facts/Variables defined by this role

Each variable listed in this section is dynamically defined when executing this role (and can only be overwritten using ansible.builtin.set_facts) and is meant to be used not just internally.

🏷️ Tags

Tasks are tagged with the following tags:

Tag Purpose

mediawiki::extensions

mediawiki::skins

You can use Ansible to skip tasks, or only run certain tasks by using these tags. By default, all tasks are run when no tags are specified.

👫 Dependencies

📚 Example Playbook Usages

Note

The machine needs to be prepared. In CI, this is done in molecule/resources/prepare.yml which sources its soft dependencies from requirements.yml:

---
- name: prepare
  hosts: all
  become: true
  gather_facts: false

  vars:
    # https://www.mediawiki.org/wiki/Compatibility
    # https://www.php.net/supported-versions.php
    php_version: "7.4"
    php_enable_webserver: true
    mysql_databases:
      - name: mediawiki
    mysql_users:
      - name: mediawiki
        password: ccc # pragma: allowlist secret
        priv: "mediawiki.*:ALL"
    openssl_items:
      - filename: mediawiki
        csr_common_name: "{{ ansible_fqdn }}"
    apache_remove_default_vhost: true
    apache_vhosts:
      - servername: "{{ ansible_fqdn }}"
        loglevel: debug
        documentroot: "/var/www/html/mediawiki"
        extra_parameters: |
          <Directory "/var/www/html/mediawiki">
              AllowOverride All
              Options None FollowSymLinks
              Require all granted
          </Directory>
          # Short URLS
          RewriteEngine On
          RewriteRule ^/?wiki(/.*)?$ %{DOCUMENT_ROOT}/index.php [L]
          RewriteRule ^/*$ %{DOCUMENT_ROOT}/index.php [L]
          # HTTPS
          SSLEngine on
          SSLCertificateFile {{ openssl_crt_directory }}/mediawiki.crt
          SSLCertificateKeyFile {{ openssl_key_directory  }}/mediawiki.key

  roles:
    - name: jonaspammer.bootstrap
    - name: jonaspammer.core_dependencies
    - name: robertdebock.epel

    - name: geerlingguy.php-versions
    - name: geerlingguy.php
    - name: geerlingguy.php-mysql
    - name: geerlingguy.composer
    - name: geerlingguy.mysql
    # apache vhost with https
    - name: jonaspammer.pip
    - name: jonaspammer.openssl
    - name: jonaspammer.apache2

The following diagram is a compilation of the "soft dependencies" of this role as well as the recursive tree of their soft dependencies.

requirements.yml dependency graph of jonaspammer.mediawiki

Example 1. Recommended Play
roles:
  - jonaspammer.mediawiki

vars:
  mediawiki_destination: "/opt/my_wiki"
  mediawiki_linux_username: "root"
  mediawiki_linux_group: "root"
Example 2. Downloading Extensions and Skins
Tip

If an extensions is under Wikimedias' version control, you will only need to supply the name property.

roles:
  - jonaspammer.mediawiki

vars:
  mediawiki_extensions:
    special_page:
      - name: "ExtendedFilelist"
        git_mwrepo_name: "BlueSpiceExtendedFilelist"
        git_run_composer_install: true
        composer_install_pre_config_actions:
          - "--no-plugins allow-plugins.composer/installers true"

    editor:
      - name: "CodeEditor"
      - name: "CodeMirror"
      - name: "VisualEditor"
      - name: "WikiEditor"

    parser:
      - name: "BOFH"
        git_url: "https://github.com/tessus/mwExtensionBOFH"
        git_version: "1.8"

    semantic_mediawiki:
      - name: "SemanticMediaWiki"
        gather_type: composer
        composer_name: "mediawiki/semantic-media-wiki"
        composer_version: "~3.0"
        composer_install_pre_config_actions:
          - "--no-plugins allow-plugins.wikimedia/composer-merge-plugin true"

    variable:
      - name: "HitCounters"
        gather_type: git  # We get it from git...
        composer_name: "mediawiki/hit-counters"  # ...but make sure that, if it was previously installed through composer, this role removes it from Mediawiki's Composer packages

  mediawiki_skins:
    - name: "Timeless"
    - name: "Vector"
    - name: "MonoBook"
    - name: "MinervaNeue"

🧪 Tested Distributions

A role may work on different distributions, like Red Hat Enterprise Linux (RHEL), even though there is no test for this exact distribution.

OS Family Distribution Distribution Release Date Distribution End of Life Accompanying Docker Image

Debian

Ubuntu 20.04 LTS

2021-04

2025-04

CI

Debian

Ubuntu 22.04 LTS

2022-04

2027-04

CI

Debian

Debian 11

2021-08

2024-06 (2026-06 LTS)

CI

Debian

Debian 12

2023-06

2026-06 (2028-06 LTS)

CI

🧪 Tested Ansible versions

The tested ansible versions try to stay equivalent with the support pattern of Ansible’s community.general collection. As of writing this is:

  • 2.13 (Ansible 6)

  • 2.14 (Ansible 7)

  • 2.15 (Ansible 8)

  • 2.16 (Ansible 9)

📝 Development

Conventional Commits pre-commit.ci status

📌 Development Machine Dependencies

  • Python 3.10 or greater

  • Docker

📌 Development Dependencies

Development Dependencies are defined in a pip requirements file named requirements-dev.txt. Example Installation Instructions for Linux are shown below:

# "optional": create a python virtualenv and activate it for the current shell session
$ python3 -m venv venv
$ source venv/bin/activate

$ python3 -m pip install -r requirements-dev.txt

ℹ️ Ansible Role Development Guidelines

Please take a look at my Ansible Role Development Guidelines.

If interested, I’ve also written down some General Ansible Role Development (Best) Practices.

🔢 Versioning

Versions are defined using Tags, which in turn are recognized and used by Ansible Galaxy.

Versions must not start with v.

When a new tag is pushed, a GitHub CI workflow (Release CI) takes care of importing the role to my Ansible Galaxy Account.

🧪 Testing

Automatic Tests are run on each Contribution using GitHub Workflows.

The Tests primarily resolve around running Molecule on a varying set of linux distributions and using various ansible versions.

The molecule test also includes a step which lints all ansible playbooks using ansible-lint to check for best practices and behaviour that could potentially be improved.

To run the tests, simply run tox on the command line. You can pass an optional environment variable to define the distribution of the Docker container that will be spun up by molecule:

$ MOLECULE_DISTRO=ubuntu2204 tox

For a list of possible values fed to MOLECULE_DISTRO, take a look at the matrix defined in .github/workflows/ci.yml.

🐛 Debugging a Molecule Container

  1. Run your molecule tests with the option MOLECULE_DESTROY=never, e.g.:

    $ MOLECULE_DESTROY=never MOLECULE_DISTRO=ubuntu1604 tox -e py3-ansible-5
    ...
      TASK [ansible-role-pip : (redacted).] ************************
      failed: [instance-py3-ansible-9] => changed=false
    ...
     ___________________________________ summary ____________________________________
      pre-commit: commands succeeded
    ERROR:   py3-ansible-9: commands failed
  2. Find out the name of the molecule-provisioned docker container:

    $ docker ps
    30e9b8d59cdf   geerlingguy/docker-debian12-ansible:latest   "/lib/systemd/systemd"   8 minutes ago   Up 8 minutes                                                                                                    instance-py3-ansible-9
  3. Get into a bash Shell of the container, and do your debugging:

    $ docker exec -it 30e9b8d59cdf /bin/bash
    
    root@instance-py3-ansible-2:/#
    Tip

    If the failure you try to debug is part of your verify.yml step and not the actual converge.yml, you may want to know that the output of ansible’s modules (vars), hosts (hostvars) and environment variables have been stored into files on both the provisioner and inside the docker machine under: * /var/tmp/vars.yml (contains host variables under the hostvars key) * /var/tmp/environment.yml grep, cat or transfer these as you wish!

    Tip

    You may also want to know that the files mentioned in the admonition above are attached to the GitHub CI Artifacts of a given Workflow run.
    This allows one to check the difference between runs and thus help in debugging what caused the bit-rot or failure in general.

    178442403 e15264ca 433a 4bc7 95db cfadb573db3c
  4. After you finished your debugging, exit it and destroy the container:

    root@instance-py3-ansible-2:/# exit
    
    $ docker stop 30e9b8d59cdf
    
    $ docker container rm 30e9b8d59cdf
    or
    $ docker container prune

🐛 Debugging installed package versions locally

Although a standard feature in tox 3, this now only happens when tox recognizes the presence of a CI variable. For example:

$ CI=true tox

🧃 TIP: Containerized Ideal Development Environment

This Project offers a definition for a "1-Click Containerized Development Environment".

This Container even enables one to run docker containers inside of it (Docker-In-Docker, dind), allowing for molecule execution.

To use it:

  1. Ensure you fullfill the the System requirements of Visual Studio Code Development Containers, optionally following the Installation-Section of the linked page section.
    This includes: Installing Docker, Installing Visual Studio Code itself, and Installing the necessary Extension.

  2. Clone the project to your machine

  3. Open the folder of the repo in Visual Studio Code (File - Open Folder…).

  4. If you get a prompt at the lower right corner informing you about the presence of the devcontainer definition, you can press the accompanying button to enter it. Otherwise, you can also execute the Visual Studio Command Remote-Containers: Open Folder in Container yourself (View - Command Palettetype in the mentioned command).

Tip

I recommend using Remote-Containers: Rebuild Without Cache and Reopen in Container once here and there as the devcontainer feature does have some problems recognizing changes made to its definition properly some times.

Note

You may need to configure your host system to enable the container to use your SSH/GPG Keys.

🍪 CookieCutter

This Project shall be kept in sync with the CookieCutter it was originally templated from using cruft (if possible) or manual alteration (if needed) to the best extend possible.

Official Example Usage of cruft update
Official Example Usage of `cruft update`

🕗 Changelog

When a new tag is pushed, an appropriate GitHub Release will be created by the Repository Maintainer to provide a proper human change log with a title and description.

ℹ️ General Linting and Styling Conventions

General Linting and Styling Conventions are automatically held up to Standards by various pre-commit hooks, at least to some extend.

Automatic Execution of pre-commit is done on each Contribution using pre-commit.ci*. Pull Requests even automatically get fixed by the same tool, at least by hooks that automatically alter files.

Note

Not to confuse: Although some pre-commit hooks may be able to warn you about script-analyzed flaws in syntax or even code to some extend (for which reason pre-commit’s hooks are part of the test suite), pre-commit itself does not run any real Test Suites. For Information on Testing, see 🧪 Testing.

Tip

Nevertheless, I recommend you to integrate pre-commit into your local development workflow yourself.

This can be done by cd’ing into the directory of your cloned project and running pre-commit install. Doing so will make git run pre-commit checks on every commit you make, aborting the commit themselves if a hook alarm’ed.

You can also, for example, execute pre-commit’s hooks at any time by running pre-commit run --all-files.

💪 Contributing

PRs Welcome Open in Visual Studio Code

The following sections are generic in nature and are used to help new contributors. The actual "Development Documentation" of this project is found under 📝 Development.

🤝 Preamble

First off, thank you for considering contributing to this Project.

Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests.

🍪 CookieCutter

This Project owns many of its files to the CookieCutter it was originally templated from.

Please check if the edit you have in mind is actually applicable to the template and if so make an appropriate change there instead. Your change may also be applicable partly to the template as well as partly to something specific to this project, in which case you would be creating multiple PRs.

💬 Conventional Commits

A casual contributor does not have to worry about following the spec by definition, as pull requests are being squash merged into one commit in the project. Only core contributors, i.e. those with rights to push to this project’s branches, must follow it (e.g. to allow for automatic version determination and changelog generation to work).

🚀 Getting Started

Contributions are made to this repo via Issues and Pull Requests (PRs). A few general guidelines that cover both:

Issues

Issues should be used to report problems, request a new feature, or to discuss potential changes before a PR is created. When you create a new Issue, a template will be loaded that will guide you through collecting and providing the information we need to investigate.

If you find an Issue that addresses the problem you’re having, please add your own reproduction information to the existing issue rather than creating a new one. Adding a reaction can also help be indicating to our maintainers that a particular problem is affecting more than just the reporter.

Pull Requests

PRs to this Project are always welcome and can be a quick way to get your fix or improvement slated for the next release. In general, PRs should:

  • Only fix/add the functionality in question OR address wide-spread whitespace/style issues, not both.

  • Add unit or integration tests for fixed or changed functionality (if a test suite already exists).

  • Address a single concern

  • Include documentation in the repo

  • Be accompanied by a complete Pull Request template (loaded automatically when a PR is created).

For changes that address core functionality or would require breaking changes (e.g. a major release), it’s best to open an Issue to discuss your proposal first.

In general, we follow the "fork-and-pull" Git workflow

  1. Fork the repository to your own Github account

  2. Clone the project to your machine

  3. Create a branch locally with a succinct but descriptive name

  4. Commit changes to the branch

  5. Following any formatting and testing guidelines specific to this repo

  6. Push changes to your fork

  7. Open a PR in our repository and follow the PR template so that we can efficiently review the changes.

🗒 Changelog

Please refer to the Release Page of this Repository for a human changelog of the corresponding Tags (Versions) of this Project.

Note that this Project adheres to Semantic Versioning. Please report any accidental breaking changes of a minor version update.

⚖️ License

MIT License

Copyright (c) 2022, Jonas Pammer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

About

An ansible role for downloading mediawiki into specified directory, installing recommended system packages and downloading additional extensions and skins.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages