An OJS Plugin to streamline codechecking of submissions and display of CODECHECK certificates.
This plugin integrates the CODECHECK process into the submission and review workflows within Open Journal Systems (OJS), allowing journals to streamline code and computational reproducibility checking of scholarly submissions. The plugin provides tools for metadata creation and certificate deposition, displaying certificates, ensuring computational transparency in published research, as well as certificate and metadata publication. Therefore the plugin connects seamlessly with the CODECHECK infrastructure.
The ojs-codecheck plugin development was started as part of the CHECK-PUB project with support from TU Delft Library.
- Submission integration: Seamless integration with the OJS submission and review workflow
- CODECHECK metadata: Built-in tools for creation and publication of CODECHECK metadata
- Certificate display: Automatically display CODECHECK certificates for verified submissions
- Customizable settings: Configure CODECHECK workflow and display preferences
- ORCID deposition: Automatically deposit CODECHECK peer-review activity to codecheckers' ORCID profiles using the ORCID Member API
- Download the plugin from the releases page or clone the repository
- Extract the plugin to your OJS
plugins/generic/directory - Navigate to Settings → Website → Plugins in your OJS admin panel
- Find "CODECHECK" and click Enable
- Configure the plugin settings as needed
OJS can list the plugin in its Plugin Gallery, so that it is installed and
upgraded from Settings → Website → Plugins → Plugin Gallery like any other
plugin. This needs OJS 3.5.0-4 or later, which added a list of gallery sources
(pkp/pkp-lib#12468). Add this
repository's plugins.xml to that list in the [security]
section of config.inc.php:
[security]
plugin_gallery_urls = '["https://pkp.sfu.ca/ojs/xml/plugins.xml","https://raw.githubusercontent.com/codecheckers/ojs-codecheck/main/plugins.xml"]'- Keep the official URL in the list. The setting replaces OJS's default rather than adding to it, so leaving it out empties the gallery of every official plugin.
- OJS caches each listing for 24 hours, so a new release can take up to a day to appear in the gallery.
- Then enable the plugin and configure it in its settings, as above.
If you are interested in the changes made to this project and the different versions, feel free to view the projects Changelog.
The 0.y.z versions of this plugin are compatible with OJS 3.5.x. They are beta releases: in use for testing, not yet recommended for production journals.
For the full features of each version, feel free to look into the Changelog.
| Plugin Version | OJS Version | Status |
|---|---|---|
Unreleased |
3.5.0+ |
Active Development |
0.y.z |
3.5.0+ |
Beta |
This plugin follows the CODECHECK brand guidelines and integrates with OJS design patterns.
| Color | Hex Code | Usage | Source |
|---|---|---|---|
| CODECHECK Main Green | #008033 |
Primary brand color, certificates, badges | CODECHECK brand |
| CODECHECK Dark Green | #006629 |
Hover states, borders, emphasis | Derived from main green (80% brightness) |
| CODECHECK Light Green | #e8f5e8 |
Certificate backgrounds, success states | Derived from main green (95% lightness) |
| Color | Hex Code | Usage | Source |
|---|---|---|---|
| Info Background | #d1ecf1 |
Information boxes, notices | Bootstrap info (OJS compatibility) |
| Info Border | #d4edda |
Information box borders | Bootstrap info (OJS compatibility) |
| Info Text | #0c5460 |
Information text, labels | Bootstrap info (OJS compatibility) |
| Details Text | #495057 |
Secondary text, descriptions | Bootstrap neutral (OJS compatibility) |
| Form Borders | #ced4da |
Input borders, form elements | Bootstrap neutral (OJS compatibility) |
| Background Light | #f8fff9 to #e8f5e8 |
Light backgrounds, certificate gradients | Custom light green variants |
- Primary Green (
#008033): Use for all CODECHECK-specific elements (certificates, badges, primary actions) - Secondary Colors: Use for supporting UI elements that need to integrate with OJS design
- Gradients: Combine primary green variants for certificate backgrounds and special elements
- Accessibility: All color combinations meet WCAG 2.1 AA contrast requirements
- Metadata creation: Assistance for creating a CODECHECK metadata file
codecheck.yml - Metadata import: If
codecheck.ymlalready exists, you can also use it instead - Manage CODECHECKs: The plugin enables you to manage your different ongoing CODECHECK tasks
- Manage the plugin: Activate through the plugin management interface and set up display preferences and workflow options
- Workflow integration: The plugin automatically integrates with your submission workflow
- Monitor certificates: View and manage CODECHECK certificates through the admin interface
- CODECHECK Process: Work with codecheckers to verify your computational work
- Certificate Integration: Certificates are automatically displayed once verification is complete
- View certificates: Explore CODECHECK certificates on published articles
- Access materials: Links to computational materials and repositories
CODECHECK certificates are recorded in a GitHub repository — the register. The
plugin reads it to find existing certificate identifiers, opens one issue per
CODECHECK in it, and, when register deposits are enabled, adds a row to its
register.csv through a pull request. Which repository is used is configured in
the plugin settings (GitHub Repository used as the CODECHECK register); the
default is codecheckers/register.
A repository used as a register has to meet the following requirements.
| Requirement | Why |
|---|---|
| Public repository | The plugin reads issues and labels without authenticating; register entries are public by design |
| Issues enabled | One issue per CODECHECK is created in the register |
A label named id assigned |
Certificate identifiers are found by filtering issues on this label. Without it the plugin finds no identifiers at all |
Labels named needs codechecker and work in progress |
A CODECHECK status change moves these two, and only these two, on the register issue. GitHub invents a label that does not exist when an issue is given one, so a register spelling them differently would collect invented labels |
Issue titles ending in … | YYYY-NNN |
The identifier is read from the part after the last |. A range, YYYY-NNN/YYYY-NNN, is also accepted; anything else is ignored |
register.csv at the repository root, with a header row |
Register deposits append a row to it. Only needed when deposits are enabled |
The settings form checks the labels and register.csv — when the configured organisation or repository changes, and
warns about whatever is missing, or that the repository could not be read at
all. It does not check on every save, because the requests count against
GitHub's unauthenticated rate limit.
A new, empty register is supported. When the register holds no issue
carrying the id assigned label, the plugin asks whether to reserve the first
identifier of the current year (YYYY-001) and open the register's first issue,
rather than failing.
Anything else that yields no identifier is refused, with the reason, because reserving would then duplicate an identifier the register already holds without the plugin being able to see it:
- the
id assignedlabel does not exist — create it first - issues carry the label but no title ends in a readable identifier such as
Author et al. | 2026-001 - the repository could not be read: check the setting, that it is public, and GitHub's rate limit
Everything the plugin posts there is signed. The register issue, each
status comment and the deposit's pull request end with a separator and a line
naming the plugin and the journal, so a register shared by several journals
shows where each post came from. The wording is the setting Signature on GitHub
posts: one text per journal, Markdown, with {$journal} and {$journalUrl}
filled in, and the default when left empty. The issue's JSON block also records
the journal's address, its OJS version and the plugin's version, under
journal.url, journal.ojsVersion and plugin.
Creating and updating register issues and depositing into register.csv are
authenticated with the personal access token from the plugin settings. A
fine-grained token scoped to the register repository alone is enough:
| Resource | Access |
|---|---|
| Issues | Read and write |
| Contents | Read and write |
| Pull requests | Read and write |
Issues read/write opens and updates the register issue and its status comments.
Contents read lets the plugin see register.csv; the deposit also commits the
updated file to a branch of its own, which needs write — with read alone
reservations and status comments work and only the deposit fails, and because
it never blocks publication that shows up as a log line and a missing register
row. Pull requests read/write opens the deposit pull request. A token for a
journal that keeps register deposits switched off needs Contents read only. A classic token with public_repo also works,
but grants access to every public repository the holder can push to.
The plugin tracks CODECHECK progress through a status system displayed in the review workflow.
| Status | Badge Color | Criteria | Description |
|---|---|---|---|
| Pending | Gray | No metadata exists | CODECHECK process has not started |
| In Progress | Yellow/Warning | Metadata exists but incomplete | Codechecker is working on verification |
| Complete | Green/Success | Certificate ID and check time both present | CODECHECK verification is finished |
The status is determined in CodecheckReviewDisplay.vue using the following logic:
function getStatus() {
if (metadata.value.certificate && metadata.value.checkTime) {
return 'complete';
} else if (hasMetadata.value) {
return 'in-progress';
}
return 'pending';
}The plugin deposits CODECHECK activity as a peer-review item to the codechecker's ORCID record. The following fields are set (see classes/Orcid/PeerReviewPayloadBuilder.php):
| Field | Value |
|---|---|
| Role | reviewer |
| Reviewer identifier | Codechecker's ORCID iD |
| Convening organization | Publisher name (Journal Settings → Masthead → Publisher) |
| Country | Journal Settings → Masthead → Country |
| City | Not set — OJS has no publisher city field |
| Group | issn:{ISSN} or orcid-generated:codecheck-ojs if no ISSN configured |
| Type | review |
| Date | Check completion date (codecheck_metadata.check_time) |
| Review container name | Journal name |
| Review identifier | Certificate DOI or source work ID (codecheck_metadata.certificate) |
| Review URL | https://doi.org/{certificate} or CODECHECK register URL |
| Subject name | Submission title |
| Subject type | journal-article |
| Subject identifier | Article DOI |
- OJS 3.5.0 or later
- PHP 8.2.0 or later
- Node.js 18+ (for frontend development)
- npm
- Composer
composer install
npm install
npm run buildAll three are required to run the plugin, not just to develop it:
composer installcreatesvendor/, which several classes load at file scope. Without it, any request reaching the CODECHECK API fails.npm run buildcreatespublic/build/build.iife.jsandpublic/build/build.css, which the plugin loads into the OJS backend.public/is not in git, so after a fresh clone the CODECHECK UI is missing until you build. Re-run after every change underresources/js/.
PHP in this plugin follows PSR-12 plus PKP's own additions — the rule set in
.php-cs-fixer.dist.php is a copy of
lib/pkp/.php_cs_rules from an OJS checkout, so plugin code reads like the core
it lives in. The tool is PHP-CS-Fixer. It has its own
dev/tools/composer.json and is not a require-dev of the plugin: the
plugin's vendor/autoload.php is loaded at file scope by runtime classes and
registers itself ahead of OJS's own autoloader, so a development tool installed
there would decide which version of a third of Symfony OJS runs against.
make deps installs it; on its own it is
composer install --working-dir=dev/tools.
make lint # report violations and exit non-zero; changes nothing
make lint-fix # rewrite the files to the standard
make hooks # install a git pre-commit hook that lints the staged PHPWithout the Makefile: dev/tools/vendor/bin/php-cs-fixer fix --dry-run --diff
and dev/tools/vendor/bin/php-cs-fixer fix.
The pre-commit hook installed by make hooks refuses a commit whose PHP does
not match the standard, and prints the diff. It never rewrites anything — the
formatting change is yours to make and to see. Bypass it once with
git commit --no-verify.
In VS Code, .vscode/extensions.json recommends
the junstyle.php-cs-fixer extension and
.vscode/settings.json points it at this checkout's
own binary and configuration, so format-on-save produces exactly what make lint checks. Install the recommended extensions when VS Code offers, and run make lint-deps
(or make deps) first — the extension calls dev/tools/vendor/bin/php-cs-fixer.
.github/workflows/lint.yml runs the same check
on every push and pull request, alongside a php -l pass over every PHP file.
This plugin uses Vite for building Vue.js components.
npm run build # production build into public/build/
npm run watch # rebuild on file changesThe bundle is an IIFE library that expects OJS's own globals (pkp.registry,
pkp.modules.vue) to exist — it registers components into the OJS Vue app rather
than mounting its own. It therefore cannot be exercised standalone; the Cypress
component tests substitute a mock pkp global.
registry/uiLocaleKeysBackend.json is generated during the build from the
t('…') calls in the Vue sources. Do not edit it by hand; add the key to
locale/en/locale.po and rebuild.
Keep each sentence in a single message and pass variable parts in as {$name}
placeholders instead of concatenating several keys — see the
PKP Translating Guide, in particular
its chapter for coders.
├── resources/
│ └── js/
│ ├── Components/* # Vue 3 components
│ └── main.js # Entry point
├── css/* # Minimal plugin CSS stylesheets
└── public/
└── build/ # Compiled assets (generated by Vite)
├── build.iife.js
└── build.cssThe plugin is developed in a standalone checkout and linked into an OJS
installation that sits next to it. A Makefile automates the whole setup —
run make help for the full list of targets.
The setup uses a MySQL/MariaDB account named ojs. Because MySQL root normally
authenticates via unix_socket, this one step needs a root shell (sudo mysql)
and only has to be done once:
CREATE USER IF NOT EXISTS 'ojs'@'localhost' IDENTIFIED BY 'ojs';
CREATE DATABASE IF NOT EXISTS ojs_codecheck_350
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON ojs_codecheck_350.* TO 'ojs'@'localhost';
FLUSH PRIVILEGES;Everything after this uses only the ojs account.
make ojs-install # download OJS into ../ojs-350 and add its dev dependencies
make setup # plugin deps + build, link into OJS, write config, load test data
make serve # http://localhost:8350 — admin / adminmake setup links this checkout to ../ojs-350/plugins/generic/codecheck, so
edits are live on the dev server with no copying. It also generates the OJS
app_key (3.5 refuses to serve any page without one), repairs the test
dataset's schema, and clears the caches OJS keeps for plugin settings.
The seeded journal is at http://localhost:8350/index.php/codecheck. See testData/README.md for the accounts and content it contains.
Useful targets:
| Target | Does |
|---|---|
make db-load |
load the test dataset |
make db-reset |
drop, recreate and reload from scratch |
make demo-db |
the same, plus the live demo seed — see Live demo |
make build / make watch |
rebuild the Vue bundle |
make test |
component tests + PHPUnit |
make screenshots |
capture every plugin UI surface to cypress/ui-screenshots/ |
make inspect URL=… |
open one page and dump screenshot, HTML and console log |
make social-preview |
render the repository's social preview image to dev/out/ |
Any value can be overridden, e.g. make serve PORT=9000 or
make setup OJS_ROOT=/path/to/other/ojs.
dev/live-demo.md is a five-minute walkthrough of the
plugin, with the steps to set it up and to capture backup slides.
make demo-db loads its dataset.
make screenshots runs a Cypress pass over the plugin settings form, the
editorial dashboard column, the workflow CODECHECK tab, the published article
sidebar, an issue table of contents and the info page, writing full-page PNGs to
cypress/ui-screenshots/.
Captures are 1920x1200; change that with
make screenshots SHOT_WIDTH=2560 SHOT_HEIGHT=1440.
For a single page, dev/inspect.mjs logs in and dumps a screenshot, the rendered
HTML and the console/network log (including failed requests) to dev/out/:
make inspect URL=http://localhost:8350/index.php/codecheck/dashboard/editorial
node dev/inspect.mjs <url> --selector '.codecheck-metadata-form' --headedBoth need make serve running in another terminal.
The image GitHub shows when the repository is linked elsewhere is built from
dev/social-preview/social-preview.html: the CODECHECK logo, the plugin name
and a mock of an article page with the plugin's sidebar block. The article is
written as markup rather than taken from a screenshot, so authors, abstract and
status can be edited there.
make social-preview # writes dev/out/social-preview.png (1280x640)It needs no OJS. GitHub has no API for the setting, so upload the PNG by hand under the repository's Settings → General → Social preview.
-
Checkout to a new Release branch
git checkout -b "release-x_y_z-0"(see CHANGELOG.md for further information on the version names)
-
Change the release in the
version.xmlto the new version specified in the Release branch name- please use the full OJS format, so
x.y.z.0 - set
<date>to the release date
- please use the full OJS format, so
-
Update
CITATION.cffto match:versionanddate-releasedcarry the same two values. The Zenodo DOI goes in after the release, in step 15. GitHub validates the file on push and shows an error in the "Cite this repository" widget if it is malformed -
Install dependencies:
npm install -
Build the frontend:
npm run build -
Ensure that:
public/build/exists (ignored by git)- and contains the compiled files (
build.iife.jsandbuild.css)
-
Test the plugin (Frontend Component Tests and PHP Unit Tests)
-
Create release tag
git commit -am "Release x.y.z.0"git tag -a vx.y.z.0 -m "Release x.y.z.0"
-
Push the branch
git push --set-upstream origin release-x_y_z-0
-
Push the tag
git push origin vx.y.z.0
-
Package the Plugin: (ensure that
vx.y.z.0matches the tag you pushed)sh package-plugin.sh --format tar.gz --version x.y.z.0
The script stages the package rather than editing an archive in place. It exports the tag (honouring the
export-ignorerules in.gitattributes), copiespublic/build/in from the working tree, runscomposer install --no-dev --prefer-dist, strips each dependency's own tests, docs and examples, and writes everything under a singlecodecheck/directory. It prints the md5 of the result and, fortar.gz, the<release>entry forplugins.xmlthat step 14 records, with the version and date taken fromversion.xmlat the tag. It refuses a tag whoseversion.xmlnames a different release.upgrade.xmlis exported with the rest, which is what makes a Plugin Gallery upgrade run the database migrations; keep it out of.gitattributes.Do not assemble the archive by hand. Three things are easy to get wrong and all three have been:
- the single top-level directory. OJS extracts the archive and looks for
one directory containing
version.xml; a flat archive is refused withmanager.plugins.invalidPluginArchive. The directory name must match<application>inversion.xml. vendor/. It is gitignored, sogit archivenever includes it, and three classesrequirevendor/autoload.phpat file scope — a package without it fatals on the first request that reaches the plugin's API.- installing from source. Without
--prefer-dist, composer leaves a.gitdirectory in every package: 27 of them, and 39 MB ofvendor/for about 4 MB of code.
- the single top-level directory. OJS extracts the archive and looks for
one directory containing
-
Double check that the package:
- Includes: a single top-level
codecheck/directory holdingversion.xml,vendor/,public/build/, all PHP files, templates, locale - Doesn't include:
node_modules/,resources/(Vue sources),.env,tests/,cypress/,dev/,testData/,Makefile,CLAUDE.md—.gitattributeskeeps these out
- Includes: a single top-level
-
Create the Release in the GitHub UI
- Tag [
]: make sure to select the tag, which you just created (vx.y.z.0) - Target [
]: select your Release branch as a target ("release-x_y_z-0") - Title: use both release number and a speaking title with terms like
"alpha"or"beta"to communicate the development status - Description: detailed description on the new features and fixes, based on the entries from the CHANGELOG.md
- Assets: upload the
codecheck-x.y.z.0.tar.gzbuilt in step 11, unchanged
- Tag [
-
Record the release in the Plugin Gallery listing, once the package is uploaded: append the
<release>blockpackage-plugin.shprinted in step 11 toplugins.xml, write its one-line description, and commit it tomain, the branch OJS reads the listing from.make test-phpchecks it.- Append, never edit. An earlier release stays as it is: its md5 pins a package journals may already have installed, so a broken package gets a new release rather than a replaced asset
-
Once only, after the first release Zenodo archives (0.1.0.0 predates the Zenodo integration, so the next release is the first): take the concept DOI from the Zenodo record, the one that stays the same across versions, not the DOI of this one version, and add it to
CITATION.cffunderidentifiersasCLAUDE.mdshows, then commit that tomainand close #8's Zenodo part. Later releases change nothing here
codecheck/
├── CHANGELOG.md # The projects Changelog with details for each version
├── CITATION.cff # How to cite the plugin; GitHub renders it as "Cite this repository"
├── CONTRIBUTING.md # Contibution guidelines for this repo
├── CodecheckPlugin.php # Main plugin class
├── LICENSE # License file
├── README.md # This documentation
├── api/* # API related classes (e.g. CodecheckApiHandler)
├── assets/* # Assets (e.g. images)
├── classes/* # Plugin classes
├── composer.json # composer json-file
├── composer.lock # composer lock-file
├── css/* # CODECHECK CSS stylesheets
├── cypress/ # Frontend tests
│ ├── support/* # mount helpers, pkp global mock, login commands
│ └── tests/
│ ├── component/* # Vue component tests (no OJS needed)
│ ├── e2e/* # end-to-end tests (need a running OJS)
│ └── visual/* # screenshot pass over the plugin UI
├── dev/* # Development helpers (page inspector, social preview image)
├── locale/* # Internationalization (language localization strings)
├── Makefile # Local development environment automation
├── package-lock.json
├── package.json
├── package-plugin.sh # Shell script, that makes packaging this plugin reproducible
├── public/build/* # NPM realese build files
├── resources/js/* # The Vue.js Components
├── templates/* # HTML templates
├── tests/* # The ojs-codecheck plugin unit tests
├── version.xml # Plugin metadata and version info
└── vite.config.js # The config file for Vite.js
If you want to contribute to this project, we kindly ask you to follow our contribution guidelines.
If you want to add a new Api Endpoint, please first register it inside the constructor of the CODECHECK Api Handler like this:
$this->endpoints = [
'Your method (e.g. GET, POST, ...)' => [
[
'route' => 'your endpoint route',
'handler' => [$this, 'yourFunction'],
'role' => CodecheckRole::class, // give the `'Role'` property a class that extends CodecheckRole
],
],
];Then define what yourFunction() should do when your Endpoint is called. It is important, that the function ends by sending a JSON response with $this->respond().
private function yourFunction(): void
{
/* Do some calculations */
// Serve your Api endpoint route
// success should be true or false along with a matching HTML response code like 200 or 404
$this->respond([
'success' => true,
'payload' => $test,
], 200);
}respond() does not return: in a served request it writes the response and ends
the process, and under test it unwinds. Nothing after it runs, so send exactly one
response per request and put any cleanup before it.
The request itself is answered by CodecheckApiHandler::execute(), not by the
constructor — constructing a handler wires it up and nothing more, which is what
lets tests/ApiUnitTests/CodecheckApiHandlerUnitTest.php drive it with a
recording JsonResponseEmitter in place of the one that echoes and exits.
Finally your defined CodecheckRoleArray can have the following PKP rules (PKP\security\Role):
| Constant | Role name |
|---|---|
Role::ROLE_ID_SITE_ADMIN |
Site Administrator |
Role::ROLE_ID_MANAGER |
Manager Journal/Press/Server Manager |
Role::ROLE_ID_SUB_EDITOR |
Sub Editor |
Role::ROLE_ID_ASSISTANT |
Editorial assistant / support role |
Role::ROLE_ID_REVIEWER |
Reviewer |
Role::ROLE_ID_AUTHOR |
Author |
Role::ROLE_ID_READER |
Reader |
Role::ROLE_ID_SUBSCRIPTION_MANAGER |
Subscription Manager |
The plugin has three test suites. Only the component tests run without an OJS installation — see Local development environment for setting one up.
| Suite | Command | Needs OJS? | Needs a running server? |
|---|---|---|---|
| Vue component tests | npm run test:component |
no | no |
| PHP unit tests | make test-php |
yes | no |
| End-to-end tests | make test-e2e |
yes | yes |
| Screenshots | make screenshots |
yes | yes |
make test runs everything that does not need a running server.
These mount the Vue components directly through Vite against a mock pkp
global, so they need nothing but npm install:
npm run test:component # headless
npm run test:component:open # interactivePHPUnit needs an OJS installation, because the tests load OJS classes and the
runner uses the PHPUnit shipped in lib/pkp. That installation must have its
development dependencies installed (composer install inside lib/pkp) —
release tarballs ship without PHPUnit. make ojs-install does this for you.
With the plugin linked into an OJS install (make setup):
make test-phpOr directly, from the tests/ directory:
sh runTests.sh # inside <ojs>/plugins/generic/codecheck
OJS_ROOT=/path/to/ojs sh runTests.sh # from a standalone checkout
sh runTests.sh --coverage-report=true # writes tests/results/index.htmlOJS_ROOT is needed whenever the plugin directory is a symlink, because PHP
resolves __FILE__ through symlinks and the default "four levels up" lookup
then points outside the OJS tree.
No tests are skipped. Coverage that would need the application booted — anything constructing a settings form — lives in the end-to-end suite instead, which exercises the real form in a real journal.
These drive a real OJS instance through the browser.
make serve # in one terminal
make test-e2e # in anotherPrerequisites:
- OJS running with the test dataset loaded (
make setup && make serve) - at least one published submission carrying CODECHECK metadata — the bundled dataset provides this
- admin credentials (
admin/admin)
The base URL defaults to http://localhost:8350 and can be pointed anywhere:
CYPRESS_BASE_URL=http://localhost:8888/ojs npm run test:e2emake screenshots walks every surface the plugin renders and writes full-page
PNGs to cypress/ui-screenshots/. It is a way to look at the UI, not a regression
suite — it only asserts that each page loads and carries its CODECHECK element.
.github/workflows/tests.yml runs all three
suites on every push and pull request to main: PHPUnit against a checkout of
pkp/ojs@stable-3_5_0 with MySQL, the Cypress component tests standalone, and
the e2e tests against a full Apache + MySQL + OJS stack seeded from
testData/.
.github/workflows/lint.yml is separate and runs
on the same events: the coding-standard check and a php -l syntax pass. It
needs neither OJS nor a database, so it answers in well under a minute — see
Code style and linting.
Copyright (c) 2025 CODECHECK Initiative
This program is free software; you can redistribute it and/or modify it under the terms of the Apache License Version 2.0, see file LICENSE.
- Documentation: CODECHECK Guide
- Issues: GitHub Issues
- Community: CODECHECK Community
- Email: For sensitive issues, contact the CODECHECK team directly at team@cdchck.science
The CHECK-PUB project (2025-2026) is empored by TU Delft Library.
