Skip to content

chore: remove dead devops tooling (travis, codeship, heroku, coveralls, arcanist, garden)#5053

Merged
dukedanny merged 2 commits into
fix/vendor-gisconverterfrom
chore/devops-cleanup
Jul 17, 2026
Merged

chore: remove dead devops tooling (travis, codeship, heroku, coveralls, arcanist, garden)#5053
dukedanny merged 2 commits into
fix/vendor-gisconverterfrom
chore/devops-cleanup

Conversation

@tuxpiper

Copy link
Copy Markdown
Member

Why

The repo carries ~10 years of CI/CD config for tools nobody uses any more. Today there is exactly one live CI system — GitHub Actions (.github/workflows/test-and-ship.yml) — plus Docker + the Makefile for local dev. Everything removed here is config wired to nothing.

This PR is purely subtractive. The three real bugs found while surveying are in a separate stacked PR so this one stays easy to review.

What's removed

Tool Files Why it's dead
Travis CI .travis.yml, .env.travis travis-ci.org shut down in 2021
Codeship codeship-{services,steps}.yml, deployment.env.encrypted, docker/{build,test,release,awscli}.Dockerfile + their .run.sh CloudBees CodeShip is EOL; these still declared PHP 7.2/7.3 services on a PHP-7.4-only repo
Coveralls .coveralls.yml, php-coveralls dev dep Nothing has uploaded coverage since 2016
Heroku 1-click app.json, Procfile, apache_heroku.conf Procfile invoked bin/heroku-php-apache2, which doesn't exist
Phabricator .arcconfig, .arclint Paths referenced the pre-Laravel Kohana tree
Garden.io garden.yaml, garden_modules/ Targets a k8s context and a buildMode modern Garden removed
librarian-puppet .librarian/ Pointed at a puppet/modules/ tree that is gone

Plus orphan files with no referrer anywhere: skeleton.php (a 2014 code template), example.env (superseded by .env.example), package-lock.json (empty — and there is no package.json), mapping.json, the root pre-commit script (superseded by captainhook.json), phpspec.yml.coverage, apiary.apib (a stub; real blueprints live in docs/api/), and tests/CaptainHook/PHPCS.php.

What is deliberately NOT removed

  • docker/release.sh — sits right next to the Codeship-only release.Dockerfile/release.run.sh but is live: .github/actions/release-tar calls it.
  • phpspec / behat — they look legacy but composer test runs both. Behat is the dominant suite (738 scenarios vs 172 unit tests).
  • *.aes / deployment.env / docker.env / vault.txt ignore rules — kept in .gitignore/.dockerignore on purpose. Old working copies may still hold those secrets, and these rules are what stops them being committed or baked into an image.

Also

  • .gitignore / .dockerignore: dropped rules for the removed tooling and the Kohana-era tree; added tmp/ (a Codeship-jet leftover that was untracked and unignored).
  • Docs: removed the dead Travis/Coveralls/Heroku badges from docs/README.md, and repointed the Gitter/IRC links (Gitter is sunset) at GitHub issues + ushahidi.com/support. The 2019 hackathon archive and the Code of Conduct venue list are left alone.
  • resources/lang/README.md: it claimed translations are pulled from Transifex automatically. There is no such CI job, and PRs do edit the English source strings directly — the stated policy was misleading.

Verification

Run against a throwaway mariadb:10.11 stack mirroring the CI job:

Check Result
composer lint (3 phpcs rulesets) ✅ all pass
phpunit ✅ 172 tests, 534 assertions
phpspec ✅ 10 specs, 42 examples
behat 738 scenarios, 6339 steps

Also verified: every deleted filename has zero remaining references (git grep), all Dockerfile COPY inputs still exist, and .github/actions/release-tar still resolves docker/release.sh.

🤖 Generated with Claude Code

@tuxpiper
tuxpiper force-pushed the chore/devops-cleanup branch from 3751a70 to c642bfe Compare July 13, 2026 17:13
@tuxpiper
tuxpiper changed the base branch from develop to fix/vendor-gisconverter July 13, 2026 17:14
…s, arcanist, garden)

GitHub Actions (.github/workflows/test-and-ship.yml) is the only CI system in use,
alongside Docker + the Makefile for local dev. Everything removed here is config for
tooling that is no longer wired to anything.

Removed:
- Travis CI: .travis.yml, .env.travis (travis-ci.org shut down in 2021)
- Codeship: codeship-{services,steps}.yml, deployment.env.encrypted, and the
  Codeship-only docker/{build,test,release,awscli}.Dockerfile + their .run.sh
  scripts. CloudBees CodeShip is EOL and these still declared PHP 7.2/7.3 services.
  docker/release.sh is NOT part of this -- it is still used by the release-tar action.
- Coveralls: .coveralls.yml + the php-coveralls dev dep (nothing has uploaded
  coverage since 2016). Drops the orphaned symfony/stopwatch transitive dep too.
- Heroku one-click deploy: app.json, Procfile, apache_heroku.conf (Procfile invoked
  bin/heroku-php-apache2, which does not exist)
- Phabricator Arcanist: .arcconfig, .arclint (paths referenced the pre-Laravel
  Kohana tree)
- Garden.io: garden.yaml, garden_modules/
- librarian-puppet: .librarian/ (pointed at a puppet/modules/ tree that is gone)

Orphan files with no referrer anywhere in the repo: skeleton.php (a 2014 code
template), example.env (superseded by .env.example), package-lock.json (empty, and
there is no package.json), mapping.json, the root pre-commit script (superseded by
captainhook.json), phpspec.yml.coverage, apiary.apib (a stub; the real blueprints
live in docs/api/), and tests/CaptainHook/PHPCS.php (orphaned when the pre-commit
hook was dropped from captainhook.json in 2022).

Also:
- .gitignore / .dockerignore: drop rules for the removed tooling and the Kohana-era
  tree. Kept the *.aes / deployment.env / docker.env / vault.txt rules on purpose --
  old working copies may still hold those secrets, and these rules are what stops
  them being committed or baked into an image. Added tmp/ (a Codeship-jet leftover
  that was untracked *and* unignored).
- docs: drop the dead Travis/Coveralls/Heroku badges, and repoint the Gitter/IRC
  links (Gitter is sunset) at GitHub issues and ushahidi.com/support. The 2019
  hackathon archive and the Code of Conduct venue list are left as-is.
- resources/lang/README.md: it claimed translations are pulled from Transifex
  automatically. There is no such CI job, and PRs do edit the English source strings
  directly, so the stated policy was misleading.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tuxpiper
tuxpiper force-pushed the chore/devops-cleanup branch from c642bfe to 3ec822f Compare July 15, 2026 14:17
…ock (#5054)

* fix: revive the inert Feature test suite, drop the dead behat Mink block

Three defects found while auditing the devops config. All verified against a
throwaway mariadb:10.11 stack mirroring the CI job.

1. The tests/Feature phpunit suite matched zero tests. phpunit.xml.dist selects
   ./tests/Feature with suffix="Test.php", but the two files there were named
   ExportJobAPI.php and WebhooksPostsUpdateAPI.php, so nothing ever ran. They had
   also rotted since the 2022 Lumen -> Laravel migration and could not simply be
   renamed: ExportJobAPI imported Laravel\Lumen\Testing\DatabaseTransactions (Lumen
   is no longer installed), WebhooksPostsUpdateAPI declared setUp()/tearDown()
   without the ': void' return types PHPUnit 9 requires, and both used the Lumen
   assertion API (seeStatusCode/seeJson/seeJsonStructure/expectsJobs), which does
   not exist on Laravel's TestCase.

   Ported both to Laravel 8 + PHPUnit 9 and renamed them so the suite collects them:
   - seeStatusCode/seeJson/seeJsonStructure -> assertStatus/assertJson/
     assertJsonStructure on the returned TestResponse
   - expectsJobs(ExportPostsJob::class) -> Bus::fake() + Bus::assertDispatched()
   - ExportJobAPI referenced \Ushahidi\Modules\Auth\GenericUser, which does not
     exist; the real class is \Ushahidi\Authzn\GenericUser

   ExportJobAPITest now creates its own admin user in setUp() instead of assuming
   user id 2. Ushahidi\Authzn\Session::getUser() loads the acting user from the
   database, and id 2 is only an admin in the behat fixture (tests/datasets), which
   phpunit never loads -- and which rewrites the users table when behat does load it.
   Owning the user keeps the suite independent of run order.

   phpunit now reports 176 tests / 552 assertions, up from 172 / 534.

2. behat.yml.dist declared a Behat\MinkExtension block, but it was indented as a
   child of suites.default rather than at profile level, so behat silently ignored
   it. That was load-bearing: mink is not in composer.lock at all, so hoisting the
   block to where it "belongs" would break all 738 scenarios with an
   extension-not-found error. Removed the block rather than fix its indentation.
   The three contexts use no Mink. behat: 738 scenarios / 6339 steps still pass.

3. .editorconfig set indent_style = spaces. The spec only accepts 'tab' or 'space',
   so editors ignored the value and indent style was unenforced. Now 'space'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: make the Vagrantfile find the Homestead.yml that ships with the repo

The Vagrantfile only looked for Homestead.yaml or Homestead.json, but the repo
ships Homestead.yml -- and .gitignore ignores the two names it did look for. So
following the setup docs ("the Vagrant and Homestead.yml files that ship with
Ushahidi", then `vagrant up`) aborted with "Homestead settings file not found".
Broken since Homestead.yml was re-added in 2023.

Add Homestead.yml to the lookup chain, after Homestead.yaml/.json so a developer's
local override still wins. Preferred over renaming the tracked file, which would
land it under a gitignored name.

Also point the abort message at the project directory it actually searches, rather
than confDir (the vendor Homestead install).

Verified statically: Vagrantfile parses (ruby -c), Homestead.yml parses as YAML and
its settings resolve, and the lookup chain now selects Homestead.yml where it
previously aborted. NOT boot-tested: Homestead.yml pins provider: virtualbox, and
VirtualBox on Apple Silicon cannot run the x86_64 Homestead box, so `vagrant up`
needs an Intel Mac or a Linux host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dukedanny

Copy link
Copy Markdown

cc @ngetichnicholas

@dukedanny
dukedanny merged commit 243630f into fix/vendor-gisconverter Jul 17, 2026
4 checks passed
dukedanny pushed a commit that referenced this pull request Jul 17, 2026
…cks CI) (#5055)

* fix: vendor symm/gisconverter, whose upstream repo was deleted

The project could not be installed from a clean checkout. symm/gisconverter's
GitHub repository no longer exists, and the dist URL recorded in composer.lock
points straight at it, so `composer install` died with:

  Failed to download symm/gisconverter from dist: The "https://api.github.com/
  repos/symm/gisconverter/zipball/21ab697b..." file could not be downloaded (404)

This broke every from-scratch build, develop included -- the last green CI run was
2026-04-21, and nothing has built from a cold cache since. It surfaced now only
because that was the last time anyone pushed a branch that had to resolve
dependencies without a warm vendor/ directory.

The library is not droppable: it does the WKT geometry decoding behind
PointRepository, BoundingBox, PostPoint, the V5 geometry query handlers and the
Twitter data source. Packagist still serves the metadata but marks the package
abandoned, and the only dist URL it offers is the dead one. No maintained fork
exists to repoint at.

So vendor it. packages/gisconverter/src is byte-identical to the v1.0.5 release
(upstream ref 21ab697b7692b891dac37c64d10c9d83d4433f80), wired up with a composer
path repository. symlink: false so composer copies it into vendor/ exactly as
before, which keeps the docker build and the release tarball unchanged. Nothing
that imports Symm\Gisconverter\... had to change.

The upstream composer.json is trimmed to what we need and pinned with an explicit
version, which a path repository requires. Upstream's tests, example.php and its
long-dead Travis config are not copied. The BSD-3-Clause licence and copyright
notice are retained as that licence requires; it is compatible with our AGPL-3.0.

src/ruleset.xml excludes packages/* from phpcs, alongside vendor/*, so the
vendored source stays byte-identical to upstream rather than being reformatted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: copy packages/ into the docker build before composer install

The image build runs `composer install` (Dockerfile line ~23) before `COPY . .`,
with only composer.json/composer.lock in the build context. symm/gisconverter is
now a path-repository package, so composer needs its source at that layer and the
build fails with:

  In PathDownloader.php line 51:
    Source path "packages/gisconverter" is not found for package symm/gisconverter

Copy packages/ into the context before the install. This only affects the `ship`
job (the Docker image build), which is push-only and skipped on PR checks -- which
is why it was not caught by the test job or the pull_request run.

Verified with a full `docker build .`: the image builds end to end and
vendor/symm/gisconverter is present and autoloadable inside it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: remove dead devops tooling (travis, codeship, heroku, coveralls, arcanist, garden) (#5053)

* chore: remove dead devops tooling (travis, codeship, heroku, coveralls, arcanist, garden)

GitHub Actions (.github/workflows/test-and-ship.yml) is the only CI system in use,
alongside Docker + the Makefile for local dev. Everything removed here is config for
tooling that is no longer wired to anything.

Removed:
- Travis CI: .travis.yml, .env.travis (travis-ci.org shut down in 2021)
- Codeship: codeship-{services,steps}.yml, deployment.env.encrypted, and the
  Codeship-only docker/{build,test,release,awscli}.Dockerfile + their .run.sh
  scripts. CloudBees CodeShip is EOL and these still declared PHP 7.2/7.3 services.
  docker/release.sh is NOT part of this -- it is still used by the release-tar action.
- Coveralls: .coveralls.yml + the php-coveralls dev dep (nothing has uploaded
  coverage since 2016). Drops the orphaned symfony/stopwatch transitive dep too.
- Heroku one-click deploy: app.json, Procfile, apache_heroku.conf (Procfile invoked
  bin/heroku-php-apache2, which does not exist)
- Phabricator Arcanist: .arcconfig, .arclint (paths referenced the pre-Laravel
  Kohana tree)
- Garden.io: garden.yaml, garden_modules/
- librarian-puppet: .librarian/ (pointed at a puppet/modules/ tree that is gone)

Orphan files with no referrer anywhere in the repo: skeleton.php (a 2014 code
template), example.env (superseded by .env.example), package-lock.json (empty, and
there is no package.json), mapping.json, the root pre-commit script (superseded by
captainhook.json), phpspec.yml.coverage, apiary.apib (a stub; the real blueprints
live in docs/api/), and tests/CaptainHook/PHPCS.php (orphaned when the pre-commit
hook was dropped from captainhook.json in 2022).

Also:
- .gitignore / .dockerignore: drop rules for the removed tooling and the Kohana-era
  tree. Kept the *.aes / deployment.env / docker.env / vault.txt rules on purpose --
  old working copies may still hold those secrets, and these rules are what stops
  them being committed or baked into an image. Added tmp/ (a Codeship-jet leftover
  that was untracked *and* unignored).
- docs: drop the dead Travis/Coveralls/Heroku badges, and repoint the Gitter/IRC
  links (Gitter is sunset) at GitHub issues and ushahidi.com/support. The 2019
  hackathon archive and the Code of Conduct venue list are left as-is.
- resources/lang/README.md: it claimed translations are pulled from Transifex
  automatically. There is no such CI job, and PRs do edit the English source strings
  directly, so the stated policy was misleading.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: revive the inert Feature test suite, drop the dead behat Mink block (#5054)

* fix: revive the inert Feature test suite, drop the dead behat Mink block

Three defects found while auditing the devops config. All verified against a
throwaway mariadb:10.11 stack mirroring the CI job.

1. The tests/Feature phpunit suite matched zero tests. phpunit.xml.dist selects
   ./tests/Feature with suffix="Test.php", but the two files there were named
   ExportJobAPI.php and WebhooksPostsUpdateAPI.php, so nothing ever ran. They had
   also rotted since the 2022 Lumen -> Laravel migration and could not simply be
   renamed: ExportJobAPI imported Laravel\Lumen\Testing\DatabaseTransactions (Lumen
   is no longer installed), WebhooksPostsUpdateAPI declared setUp()/tearDown()
   without the ': void' return types PHPUnit 9 requires, and both used the Lumen
   assertion API (seeStatusCode/seeJson/seeJsonStructure/expectsJobs), which does
   not exist on Laravel's TestCase.

   Ported both to Laravel 8 + PHPUnit 9 and renamed them so the suite collects them:
   - seeStatusCode/seeJson/seeJsonStructure -> assertStatus/assertJson/
     assertJsonStructure on the returned TestResponse
   - expectsJobs(ExportPostsJob::class) -> Bus::fake() + Bus::assertDispatched()
   - ExportJobAPI referenced \Ushahidi\Modules\Auth\GenericUser, which does not
     exist; the real class is \Ushahidi\Authzn\GenericUser

   ExportJobAPITest now creates its own admin user in setUp() instead of assuming
   user id 2. Ushahidi\Authzn\Session::getUser() loads the acting user from the
   database, and id 2 is only an admin in the behat fixture (tests/datasets), which
   phpunit never loads -- and which rewrites the users table when behat does load it.
   Owning the user keeps the suite independent of run order.

   phpunit now reports 176 tests / 552 assertions, up from 172 / 534.

2. behat.yml.dist declared a Behat\MinkExtension block, but it was indented as a
   child of suites.default rather than at profile level, so behat silently ignored
   it. That was load-bearing: mink is not in composer.lock at all, so hoisting the
   block to where it "belongs" would break all 738 scenarios with an
   extension-not-found error. Removed the block rather than fix its indentation.
   The three contexts use no Mink. behat: 738 scenarios / 6339 steps still pass.

3. .editorconfig set indent_style = spaces. The spec only accepts 'tab' or 'space',
   so editors ignored the value and indent style was unenforced. Now 'space'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: make the Vagrantfile find the Homestead.yml that ships with the repo

The Vagrantfile only looked for Homestead.yaml or Homestead.json, but the repo
ships Homestead.yml -- and .gitignore ignores the two names it did look for. So
following the setup docs ("the Vagrant and Homestead.yml files that ship with
Ushahidi", then `vagrant up`) aborted with "Homestead settings file not found".
Broken since Homestead.yml was re-added in 2023.

Add Homestead.yml to the lookup chain, after Homestead.yaml/.json so a developer's
local override still wins. Preferred over renaming the tracked file, which would
land it under a gitignored name.

Also point the abort message at the project directory it actually searches, rather
than confDir (the vendor Homestead install).

Verified statically: Vagrantfile parses (ruby -c), Homestead.yml parses as YAML and
its settings resolve, and the lookup chain now selects Homestead.yml where it
previously aborted. NOT boot-tested: Homestead.yml pins provider: virtualbox, and
VirtualBox on Apple Silicon cannot run the x86_64 Homestead box, so `vagrant up`
needs an Intel Mac or a Linux host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants