Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e6b340f8c | ||
|
|
04e47a2e6d | ||
|
|
572f5027d6 | ||
|
|
235e0268c2 | ||
|
|
65d639853b | ||
|
|
e856bbffec | ||
|
|
3ee5b789ce | ||
|
|
7f5722ff75 | ||
|
|
50b596af39 | ||
|
|
af06c4d81e | ||
|
|
41ed692299 | ||
|
|
31214f0af0 | ||
|
|
aceaa6b957 | ||
|
|
cd0e0f0e61 | ||
|
|
270e5b970f | ||
|
|
5dac3211ff | ||
|
|
4d91fc8ead |
@@ -20,14 +20,32 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }} # Use PR head when available, otherwise the pushed SHA.
|
||||
fetch-depth: 0 # a full history is required for pull request analysis
|
||||
- name: Mark repository as safe for Git
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
- name: Prepare Qodana cache directories
|
||||
run: |
|
||||
mkdir -p "${RUNNER_TEMP}/qodana/caches"
|
||||
mkdir -p "${RUNNER_TEMP}/qodana/results"
|
||||
- name: Detect Qodana Cloud token
|
||||
id: qodana-token
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
|
||||
run: |
|
||||
if [ -n "${QODANA_TOKEN:-}" ]; then
|
||||
echo "present=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "present=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@v2025.3
|
||||
if: ${{ steps.qodana-token.outputs.present == 'true' }}
|
||||
uses: JetBrains/qodana-action@v2026.1
|
||||
with:
|
||||
pr-mode: false
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
|
||||
QODANA_ENDPOINT: 'https://qodana.cloud'
|
||||
|
||||
- name: 'Skip Qodana Scan (missing cloud token)'
|
||||
if: ${{ steps.qodana-token.outputs.present != 'true' }}
|
||||
run: echo "Skipping Qodana because QODANA_TOKEN is not configured for this repository."
|
||||
|
||||
@@ -144,6 +144,7 @@ jobs:
|
||||
set -euo pipefail
|
||||
cp .github/ci.env .env
|
||||
cp .github/ci.env.staging .env.staging
|
||||
printf '\nEDGE_PUBLIC_BROKER_URL=http://edge-broker:4300\n' >> .env
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
@@ -151,7 +152,7 @@ jobs:
|
||||
node-version: 22
|
||||
|
||||
- name: Boot local stack
|
||||
run: docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml up -d traefik redis mysql-debug edge-broker php1 caddy
|
||||
run: docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml up -d traefik redis mysql-debug edge-broker php1 php2 php3 php4 php5 caddy
|
||||
|
||||
- name: Sync PHP app checkout
|
||||
run: >
|
||||
@@ -240,6 +241,7 @@ jobs:
|
||||
-e EDGE_GATEWAY_E2E_BASE_URL="http://caddy" \
|
||||
-e EDGE_GATEWAY_E2E_COMPOSE_PROJECT="$compose_project" \
|
||||
-e EDGE_GATEWAY_E2E_COPY_CONFIG="true" \
|
||||
-e EDGE_GATEWAY_E2E_SKIP_COMPOSE_UP="true" \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-w /workspace \
|
||||
node:22-alpine \
|
||||
|
||||
@@ -10,7 +10,7 @@ import { promisify } from "node:util";
|
||||
import { DEFAULT_CONFIG_FILE_NAME, DEFAULT_HOST_API_URL } from "./test-gateway.mjs";
|
||||
|
||||
const execFile = promisify(execFileCallback);
|
||||
const COMPOSE_SERVICES = ["traefik", "redis", "mysql-debug", "edge-broker", "php1", "caddy"];
|
||||
const COMPOSE_SERVICES = ["traefik", "redis", "mysql-debug", "edge-broker", "php1", "php2", "php3", "php4", "php5", "caddy"];
|
||||
|
||||
function composeArgs(projectName, args) {
|
||||
return ["compose", "-p", projectName, ...args];
|
||||
@@ -514,6 +514,10 @@ function shouldCopyGatewayConfig() {
|
||||
return /^(1|true|yes)$/i.test(String(process.env.EDGE_GATEWAY_E2E_COPY_CONFIG || "").trim());
|
||||
}
|
||||
|
||||
function shouldSkipComposeUp() {
|
||||
return /^(1|true|yes)$/i.test(String(process.env.EDGE_GATEWAY_E2E_SKIP_COMPOSE_UP || "").trim());
|
||||
}
|
||||
|
||||
function collectMessages(rows) {
|
||||
return Array.isArray(rows)
|
||||
? rows
|
||||
@@ -570,7 +574,9 @@ async function main() {
|
||||
let runnerNetworkAttached = false;
|
||||
|
||||
try {
|
||||
await ensureComposeServices(rootDir, composeProject);
|
||||
if (!shouldSkipComposeUp()) {
|
||||
await ensureComposeServices(rootDir, composeProject);
|
||||
}
|
||||
runnerNetworkAttached = await connectCurrentContainerToComposeNetwork(rootDir, composeProject);
|
||||
baseUrl = await waitForApiReady(baseUrl, rootDir, composeProject, runnerNetworkAttached);
|
||||
process.stdout.write(`Using API base URL ${baseUrl}\n`);
|
||||
|
||||
@@ -25,6 +25,16 @@ function composeArgs(projectName, args) {
|
||||
return ["compose", "-p", projectName, ...args];
|
||||
}
|
||||
|
||||
function usesWindowsPathSyntax(filePath) {
|
||||
return /^[A-Za-z]:($|[\\/])/.test(filePath) || filePath.startsWith("\\\\") || filePath.includes("\\");
|
||||
}
|
||||
|
||||
function pathForInputs(...filePaths) {
|
||||
const hasWindowsPath = filePaths.some((filePath) => usesWindowsPathSyntax(String(filePath || "")));
|
||||
|
||||
return hasWindowsPath ? path.win32 : path;
|
||||
}
|
||||
|
||||
async function resolveRootDir(scriptPath) {
|
||||
const cwd = process.cwd();
|
||||
|
||||
@@ -66,7 +76,7 @@ export function resolveComposeProjectName(rootDir, env = process.env) {
|
||||
return explicit;
|
||||
}
|
||||
|
||||
return path.basename(rootDir);
|
||||
return pathForInputs(rootDir).basename(rootDir);
|
||||
}
|
||||
|
||||
export function resolveComposeNetworkName(rootDir, env = process.env) {
|
||||
@@ -74,11 +84,13 @@ export function resolveComposeNetworkName(rootDir, env = process.env) {
|
||||
}
|
||||
|
||||
export function resolveConfigDirectory(rootDir, explicitDir = null) {
|
||||
const pathModule = pathForInputs(rootDir, explicitDir);
|
||||
|
||||
if (explicitDir) {
|
||||
return path.resolve(rootDir, explicitDir);
|
||||
return pathModule.resolve(rootDir, explicitDir);
|
||||
}
|
||||
|
||||
return path.join(rootDir, ".tmp", "test-gateway");
|
||||
return pathModule.join(rootDir, ".tmp", "test-gateway");
|
||||
}
|
||||
|
||||
export function shouldClaimGateway(existingConfig = {}, installToken = "") {
|
||||
|
||||
@@ -464,6 +464,7 @@ trait selfserve_lane_command_t
|
||||
* @param selfserve_lane_command_arguments $arguments The arguments for the command
|
||||
* @return selfserve_lane|selfserve_lane_command_t
|
||||
* @throws Exception If the command cannot be executed
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function execute(selfserve_lane_command $command, selfserve_lane_command_arguments $arguments): self
|
||||
{
|
||||
@@ -517,6 +518,7 @@ trait selfserve_lane_command_t
|
||||
// Open the entrance port before marking the lane occupied. Gateway timeouts are
|
||||
// ambiguous because the relay may already have received the pulse.
|
||||
$this->openEntrancePortForWashStart();
|
||||
$this->turnOnCleanerRelayForWashStart();
|
||||
} catch (\Throwable $e) {
|
||||
$this->setCustomerNumber($previous_customer_number);
|
||||
$this->setLicensePlate($previous_license_plate);
|
||||
|
||||
@@ -124,7 +124,7 @@ trait selfserve_lane_relay_controller_t
|
||||
*/
|
||||
public function setMachineRelayStatusHard(bool $on): bool
|
||||
{
|
||||
return $this->setRelayStatusHard(selfserve_lane_relay::MACHINE, $on);
|
||||
return $this->setRelayStatusHard(selfserve_lane_relay::MACHINE_PROGRAM_PICKER, $on);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,6 @@ it('rejects subuser sessions before checking replication permissions', function
|
||||
expect($content)->toContain("Subuser sessions cannot manage replication.");
|
||||
expect($content)->toContain("\$response->error('Subuser sessions cannot manage replication.', 403);");
|
||||
expect($content)->toContain('return $this->requirePermission($permission);');
|
||||
expect(preg_match_all("/requireClassicSuperuserPermission\\('superuser_replication_/", $content))->toBe(10);
|
||||
expect(preg_match_all("/requireClassicSuperuserPermission\\('superuser_replication_/", $content))->toBe(11);
|
||||
expect($content)->not->toContain("requirePermission('superuser_replication_");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user