Commit 984143d9 authored by Addshore's avatar Addshore 🏄
Browse files

dev: Add initial quibble support

parent 834c5058
......@@ -22,7 +22,6 @@ import (
"os"
"os/signal"
"os/user"
"strings"
"syscall"
"time"
......@@ -435,11 +434,11 @@ var mwddMediawikiComposerCmd = &cobra.Command{
Example: " composer info\n composer install -- --ignore-platform-reqs",
Run: func(cmd *cobra.Command, args []string) {
mwdd.DefaultForUser().EnsureReady()
mwdd.DefaultForUser().DockerExec(applyRelevantWorkingDirectory(mwdd.DockerExecCommand{
mwdd.DefaultForUser().DockerExec(applyRelevantMediawikiWorkingDirectory(mwdd.DockerExecCommand{
DockerComposeService: "mediawiki",
Command: append([]string{"composer"}, args...),
User: User,
}))
}, "/var/www/html/w"))
},
}
......@@ -505,25 +504,20 @@ var mwddMediawikiExecCmd = &cobra.Command{
Short: "Executes a command in the MediaWiki container",
Run: func(cmd *cobra.Command, args []string) {
mwdd.DefaultForUser().EnsureReady()
mwdd.DefaultForUser().DockerExec(applyRelevantWorkingDirectory(mwdd.DockerExecCommand{
mwdd.DefaultForUser().DockerExec(applyRelevantMediawikiWorkingDirectory(mwdd.DockerExecCommand{
DockerComposeService: "mediawiki",
Command: args,
User: User,
}))
}, "/var/www/html/w"))
},
}
var applyRelevantWorkingDirectory = func(dockerExecCommand mwdd.DockerExecCommand) mwdd.DockerExecCommand {
currentWorkingDirectory, _ := os.Getwd()
mountedMwDirectory := mwdd.DefaultForUser().Env().Get("MEDIAWIKI_VOLUMES_CODE")
// For paths inside the mediawiki path, rewrite things
if strings.HasPrefix(currentWorkingDirectory, mountedMwDirectory) {
dockerExecCommand.WorkingDir = strings.Replace(currentWorkingDirectory, mountedMwDirectory, "/var/www/html/w", 1)
var applyRelevantMediawikiWorkingDirectory = func(dockerExecCommand mwdd.DockerExecCommand, mountTo string) mwdd.DockerExecCommand {
if resolvedPath := paths.ResolveMountForCwd(mwdd.DefaultForUser().Env().Get("MEDIAWIKI_VOLUMES_CODE"), mountTo); resolvedPath != nil {
dockerExecCommand.WorkingDir = *resolvedPath
} else {
// Otherwise just use the root of mediawiki
dockerExecCommand.WorkingDir = "/var/www/html/w"
dockerExecCommand.WorkingDir = mountTo
}
return dockerExecCommand
}
......
......@@ -59,11 +59,11 @@ var mwddMediawikiFreshCmd = &cobra.Command{
Verbosity: Verbosity,
}
mwdd.DefaultForUser().UpDetached([]string{"mediawiki-fresh"}, options)
mwdd.DefaultForUser().DockerRun(applyRelevantWorkingDirectory(mwdd.DockerExecCommand{
mwdd.DefaultForUser().DockerRun(applyRelevantMediawikiWorkingDirectory(mwdd.DockerExecCommand{
DockerComposeService: "mediawiki-fresh",
Command: args,
User: User,
}))
}, "/var/www/html/w"))
},
}
......
/*Package cmd is used for command line.
Copyright © 2020 Addshore
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
import (
"os"
"github.com/spf13/cobra"
"gitlab.wikimedia.org/releng/cli/internal/exec"
"gitlab.wikimedia.org/releng/cli/internal/mwdd"
)
var mwddMediawikiQuibbleCmd = &cobra.Command{
Use: "quibble ...",
Short: "Runs commands in a 'quibble' container.",
Long: `Runs commands in a 'quibble' container.
https://doc.wikimedia.org/quibble/
THis integration is WORK IN PROGRESS`,
Example: ` # Start an interactive terminal in the quibble container
quibble bash
# Get help for the quibble CLI tool
quibble quibble -- --help
# Run php-unit quibble stage using your mwdd LocalSettings.php, skipping anything that alters your installation
quibble quibble -- --skip-zuul --skip-deps --skip-install --db-is-external --run phpunit-unit
Gotchas:
- This is a WORK IN PROGRESS integration, so don't expect all quibble features to work.
- quibble will run tests for ALL checked out extensions by default.
- If you let quibble touch your setup (missing --skip-install for example) it might break your environment.
- quibble has various things hardcoded :(, for example the user and password for browser tests, you might find the below commmand helpful.
mw docker mediawiki exec php maintenance/CeateAndPromote.php -- --sysop WikiAdmin testwikijenkinspass`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
os.Exit(1)
}
mwdd.DefaultForUser().EnsureReady()
options := exec.HandlerOptions{
Verbosity: Verbosity,
}
mwdd.DefaultForUser().UpDetached([]string{"mediawiki-quibble"}, options)
mwdd.DefaultForUser().DockerRun(applyRelevantMediawikiWorkingDirectory(mwdd.DockerExecCommand{
DockerComposeService: "mediawiki-quibble",
Command: args,
User: User,
}, "/workspace/src"))
},
}
func init() {
mwddMediawikiCmd.AddCommand(mwddMediawikiQuibbleCmd)
mwddMediawikiQuibbleCmd.Flags().StringVarP(&User, "user", "u", mwdd.UserAndGroupForDockerExecution(), "User to run as, defaults to current OS user uid:gid")
}
/*Package paths in internal utils is functionality for interacting with paths in generic ways
Copyright © 2020 Addshore
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package paths
import (
"os"
"strings"
)
/*ResolveMountForCwd ...*/
func ResolveMountForCwd(mountFrom string, mountTo string) *string {
cwd, _ := os.Getwd()
return resolveMountForDirectory(mountFrom, mountTo, cwd)
}
func resolveMountForDirectory(mountFrom string, mountTo string, directory string) *string {
// If the directory that we are in is part of the mount point
if strings.HasPrefix(directory, mountFrom) {
// We can use that mount point with any path suffix (other directories) appended
modified := strings.Replace(directory, mountFrom, mountTo, 1)
return &modified
}
// Otherwise we don't know where we are and can't help
return nil
}
/*Package paths in internal utils is functionality for interacting with paths in generic ways
Copyright © 2020 Addshore
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package paths
import (
"os"
"testing"
)
func TestResolveMountForCwd(t *testing.T) {
cwd, _ := os.Getwd()
app := "/app"
type args struct {
mountFrom string
mountTo string
}
tests := []struct {
name string
args args
want *string
}{
{
name: "no known path",
args: args{
mountFrom: "/a",
mountTo: "/b",
},
want: nil,
},
{
name: "known path",
args: args{
mountFrom: cwd,
mountTo: "/app",
},
want: &app,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ResolveMountForCwd(tt.args.mountFrom, tt.args.mountTo); !pointerStringsMatch(got, tt.want) {
t.Errorf("ResolveMountForCwd() = %v, want %v", pointerStringToString(got), pointerStringToString(tt.want))
}
})
}
}
func Test_resolveMountForDirectory(t *testing.T) {
type args struct {
mountFrom string
mountTo string
directory string
}
b := "/b"
bFoo := "/b/foo"
tests := []struct {
name string
args args
want *string
}{
{
name: "no known path",
args: args{
mountFrom: "/a",
mountTo: "/b",
directory: "/c",
},
want: nil,
},
{
name: "known path",
args: args{
mountFrom: "/a",
mountTo: "/b",
directory: "/a",
},
want: &b,
},
{
name: "known sub path",
args: args{
mountFrom: "/a",
mountTo: "/b",
directory: "/a/foo",
},
want: &bFoo,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := resolveMountForDirectory(tt.args.mountFrom, tt.args.mountTo, tt.args.directory); !pointerStringsMatch(got, tt.want) {
t.Errorf("resolveMountForDirectory() = %v, want %v", pointerStringToString(got), pointerStringToString(tt.want))
}
})
}
}
func pointerStringsMatch(a *string, b *string) bool {
return pointerStringToString(a) == pointerStringToString(b)
}
func pointerStringToString(a *string) string {
if a == nil {
return "*nil*"
}
return *a
}
version: '3.7'
# Service wrapper around what is provided by quibble
# https://doc.wikimedia.org/quibble/
services:
mediawiki-quibble:
image: docker-registry.wikimedia.org/releng/quibble-buster-php74:1.1.1
entrypoint: /bin/sh
command: -c "echo started"
working_dir: /var/www/html/w
networks:
- dps
dns:
- 10.0.0.10
volumes:
# Only mount code and config, don't mount logs or image
# TODO is this bit of config even needed?
- "${MEDIAWIKI_VOLUMES_CODE}:/workspace/src:cached"
- ./mediawiki:/mwdd:ro
# TODO cache should be mounted from the user machine?
- mw-quibble-workspace-cache:/workspace/cache
- mw-quibble-workspace-log:/workspace/log
- mw-quibble-workspace-ref:/workspace/ref
volumes:
mw-quibble-workspace-cache:
mw-quibble-workspace-log:
mw-quibble-workspace-ref:
\ No newline at end of file
......@@ -20,7 +20,11 @@ if ( PHP_SAPI === 'cli' && !defined( 'MW_DB' ) ) {
}
# Detect usage of update.php, so we can turn of replication https://phabricator.wikimedia.org/T283417
$dockerIsRunningUpdate = basename( $_SERVER['argv'][0] ) === 'update.php';
$dockerIsRunningUpdate = false;
# Sometimes argv is not set, such as when running php built in web server via quibble
if(array_key_exists('argv', $_SERVER)){
$dockerIsRunningUpdate = basename( $_SERVER['argv'][0] ) === 'update.php';
}
# Must be above WebRequest::detectServer.
# mwdd uses a proxy server with no default ports.
......
......@@ -48,9 +48,13 @@ cd mediawiki
./../bin/mw docker mediawiki exec -- composer phpunit tests/phpunit/unit/includes/PingbackTest.php
./../bin/mw docker mediawiki exec -- composer phpunit tests/phpunit/unit/includes/PingbackTest.php | grep -q "OK "
# fresh: Make sur a basic browser test works
# fresh: Make sue a basic browser test works
./../bin/mw docker mediawiki fresh npm run selenium-test -- -- --spec tests/selenium/specs/page.js
# quibble: Make sure a quibble works
./../bin/mw docker mediawiki quibble quibble -- --help
./../bin/mw docker mediawiki quibble quibble -- --skip-zuul --skip-deps --skip-install --db-is-external --command "ls"
# cd to Vector
cd skins/Vector
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment