Skip to content

Commit 1e60ef5

Browse files
committed
fix: e2e tests run in CI, pin e2e workflow deps
- Remove verbose logging from Dockerfile - pin dependent actions in new e2e workflow to their respective commits - refactor the tests to work slightly more robustly (handle creds, etc)
1 parent f339b93 commit 1e60ef5

File tree

5 files changed

+142
-55
lines changed

5 files changed

+142
-55
lines changed

.github/workflows/e2e.yml

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,43 @@ jobs:
2626
2727
steps:
2828
- name: Checkout code
29-
uses: actions/checkout@v4
29+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
3030
with:
3131
# When triggered by comment, checkout the PR branch
3232
ref: ${{ github.event_name == 'issue_comment' && format('refs/pull/{0}/head', github.event.issue.number) || github.ref }}
3333

34-
- name: Add reaction to comment
35-
if: github.event_name == 'issue_comment'
36-
uses: peter-evans/create-or-update-comment@v4
37-
with:
38-
token: ${{ secrets.GITHUB_TOKEN }}
39-
comment-id: ${{ github.event.comment.id }}
40-
reactions: eyes
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435
36+
37+
- name: Set up Docker Compose
38+
uses: docker/setup-compose-action@364cc21a5de5b1ee4a7f5f9d3fa374ce0ccde746
4139

4240
- name: Set up Node.js
43-
uses: actions/setup-node@v4
41+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
4442
with:
45-
node-version: '18'
43+
node-version: '20'
4644
cache: 'npm'
4745

4846
- name: Install dependencies
4947
run: npm ci
5048

49+
- name: Configure Git for CI
50+
run: |
51+
git config --global user.name "CI Runner"
52+
git config --global user.email "ci@example.com"
53+
git config --global init.defaultBranch main
54+
5155
- name: Build and start services with Docker Compose
52-
run: docker-compose up -d --build
56+
run: docker compose up -d --build
5357

5458
- name: Wait for services to be ready
5559
run: |
56-
timeout 60 bash -c 'until docker-compose ps | grep -q "Up"; do sleep 2; done'
60+
timeout 60 bash -c 'until docker compose ps | grep -q "Up"; do sleep 2; done'
5761
sleep 10
5862
5963
- name: Run E2E tests
6064
run: npm run test:e2e
61-
env:
62-
GIT_PROXY_URL: http://localhost:8000
63-
GIT_PROXY_UI_URL: http://localhost:8081
64-
E2E_TIMEOUT: 30000
6565

6666
- name: Stop services
6767
if: always()
68-
run: docker-compose down -v
68+
run: docker compose down -v

Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ WORKDIR /app
99
COPY package*.json ./
1010

1111
# Install all dependencies (including dev dependencies for building)
12-
RUN npm pkg delete scripts.prepare && npm ci --include=dev --loglevel verbose
12+
RUN npm pkg delete scripts.prepare && npm ci --include=dev
1313

1414
# Copy source files and config files needed for build
1515
COPY tsconfig.json tsconfig.publish.json proxy.config.json config.schema.json integration-test.config.json vite.config.ts index.html index.ts ./
1616
COPY src/ /app/src/
1717
COPY public/ /app/public/
1818

1919
# Build the UI and server
20-
RUN npm run build-ui --loglevel verbose \
20+
RUN npm run build-ui \
2121
&& npx tsc --project tsconfig.publish.json \
2222
&& cp config.schema.json dist/
2323

2424
# Prune dev dependencies after build is complete
25-
RUN npm prune --production
25+
RUN npm prune --omit=dev
2626

2727
# Production stage
2828
FROM node:20-slim AS production

tests/e2e/fetch.test.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
1+
/**
2+
* @license
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
121
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
222
import { execSync } from 'child_process';
3-
import { testConfig, waitForService, configureGitCredentials } from './setup';
23+
import { testConfig } from './setup';
424
import fs from 'fs';
525
import path from 'path';
626
import os from 'os';
@@ -9,9 +29,6 @@ describe('Git Proxy E2E - Repository Fetch Tests', () => {
929
const tempDir: string = path.join(os.tmpdir(), 'git-proxy-e2e-tests', Date.now().toString());
1030

1131
beforeAll(async () => {
12-
// Ensure the git proxy service is ready
13-
await waitForService(`${testConfig.gitProxyUiUrl}/api/v1/healthcheck`);
14-
1532
// Create temp directory for test clones
1633
fs.mkdirSync(tempDir, { recursive: true });
1734

@@ -22,15 +39,16 @@ describe('Git Proxy E2E - Repository Fetch Tests', () => {
2239
it(
2340
'should successfully fetch coopernetes/test-repo through git proxy',
2441
async () => {
25-
const repoUrl: string = `${testConfig.gitProxyUrl}/coopernetes/test-repo.git`;
42+
// Build URL with embedded credentials for reliable authentication
43+
const baseUrl = new URL(testConfig.gitProxyUrl);
44+
baseUrl.username = testConfig.gitUsername;
45+
baseUrl.password = testConfig.gitPassword;
46+
const repoUrl = `${baseUrl.toString()}/coopernetes/test-repo.git`;
2647
const cloneDir: string = path.join(tempDir, 'test-repo-clone');
2748

28-
console.log(`Cloning ${repoUrl} to ${cloneDir}`);
49+
console.log(`Cloning ${testConfig.gitProxyUrl}/coopernetes/test-repo.git to ${cloneDir}`);
2950

3051
try {
31-
// Configure git credentials locally in the temp directory
32-
configureGitCredentials(tempDir);
33-
3452
// Use git clone to fetch the repository through the proxy
3553
const gitCloneCommand: string = `git clone ${repoUrl} ${cloneDir}`;
3654
const output: string = execSync(gitCloneCommand, {
@@ -65,10 +83,14 @@ describe('Git Proxy E2E - Repository Fetch Tests', () => {
6583
it(
6684
'should successfully fetch finos/git-proxy through git proxy',
6785
async () => {
68-
const repoUrl: string = `${testConfig.gitProxyUrl}/finos/git-proxy.git`;
86+
// Build URL with embedded credentials for reliable authentication
87+
const baseUrl = new URL(testConfig.gitProxyUrl);
88+
baseUrl.username = testConfig.gitUsername;
89+
baseUrl.password = testConfig.gitPassword;
90+
const repoUrl = `${baseUrl.toString()}/finos/git-proxy.git`;
6991
const cloneDir: string = path.join(tempDir, 'git-proxy-clone');
7092

71-
console.log(`Cloning ${repoUrl} to ${cloneDir}`);
93+
console.log(`Cloning ${testConfig.gitProxyUrl}/finos/git-proxy.git to ${cloneDir}`);
7294

7395
try {
7496
const gitCloneCommand: string = `git clone ${repoUrl} ${cloneDir}`;

tests/e2e/push.test.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
1+
/**
2+
* @license
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
121
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
222
import { execSync } from 'child_process';
3-
import { testConfig, waitForService, configureGitCredentials } from './setup';
23+
import { testConfig } from './setup';
424
import fs from 'fs';
525
import path from 'path';
626
import os from 'os';
@@ -9,9 +29,6 @@ describe('Git Proxy E2E - Repository Push Tests', () => {
929
const tempDir: string = path.join(os.tmpdir(), 'git-proxy-push-e2e-tests', Date.now().toString());
1030

1131
beforeAll(async () => {
12-
// Ensure the git proxy service is ready
13-
await waitForService(`${testConfig.gitProxyUiUrl}/api/v1/healthcheck`);
14-
1532
// Create temp directory for test clones
1633
fs.mkdirSync(tempDir, { recursive: true });
1734

@@ -22,15 +39,18 @@ describe('Git Proxy E2E - Repository Push Tests', () => {
2239
it(
2340
'should handle push operations through git proxy (with proper authorization check)',
2441
async () => {
25-
const repoUrl: string = `${testConfig.gitProxyUrl}/coopernetes/test-repo.git`;
42+
// Build URL with embedded credentials for reliable authentication
43+
const baseUrl = new URL(testConfig.gitProxyUrl);
44+
baseUrl.username = testConfig.gitUsername;
45+
baseUrl.password = testConfig.gitPassword;
46+
const repoUrl = `${baseUrl.toString()}/coopernetes/test-repo.git`;
2647
const cloneDir: string = path.join(tempDir, 'test-repo-push');
2748

28-
console.log(`Testing push operation to ${repoUrl}`);
49+
console.log(
50+
`Testing push operation to ${testConfig.gitProxyUrl}/coopernetes/test-repo.git`,
51+
);
2952

3053
try {
31-
// Configure git credentials for authentication
32-
configureGitCredentials(tempDir);
33-
3454
// Step 1: Clone the repository
3555
console.log('Step 1: Cloning repository...');
3656
const gitCloneCommand: string = `git clone ${repoUrl} ${cloneDir}`;
@@ -48,9 +68,6 @@ describe('Git Proxy E2E - Repository Push Tests', () => {
4868
expect(fs.existsSync(cloneDir)).toBe(true);
4969
expect(fs.existsSync(path.join(cloneDir, '.git'))).toBe(true);
5070

51-
// Configure git credentials in the cloned repository for push operations
52-
configureGitCredentials(cloneDir);
53-
5471
// Step 2: Make a dummy change
5572
console.log('Step 2: Creating dummy change...');
5673
const timestamp: string = new Date().toISOString();

tests/e2e/setup.ts

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
/**
2+
* @license
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
121
import { beforeAll } from 'vitest';
222

323
// Environment configuration - can be overridden for different environments
@@ -26,18 +46,46 @@ export const testConfig = {
2646
export function configureGitCredentials(tempDir: string): void {
2747
const { execSync } = require('child_process');
2848

29-
// Configure git credentials using URL rewriting
30-
const baseUrlParsed = new URL(testConfig.gitProxyBaseUrl);
31-
const credentialUrl = `${baseUrlParsed.protocol}//${testConfig.gitUsername}:${testConfig.gitPassword}@${baseUrlParsed.host}${baseUrlParsed.pathname}`;
32-
const insteadOfUrl = testConfig.gitProxyBaseUrl;
49+
try {
50+
// Configure git credentials using URL rewriting
51+
const baseUrlParsed = new URL(testConfig.gitProxyBaseUrl);
3352

34-
execSync('git init', { cwd: tempDir, encoding: 'utf8' });
35-
execSync(`git config url."${credentialUrl}".insteadOf ${insteadOfUrl}`, {
36-
cwd: tempDir,
37-
encoding: 'utf8',
38-
});
53+
// Initialize git if not already done
54+
try {
55+
execSync('git rev-parse --git-dir', { cwd: tempDir, encoding: 'utf8', stdio: 'pipe' });
56+
} catch {
57+
execSync('git init', { cwd: tempDir, encoding: 'utf8' });
58+
}
3959

40-
console.log(`Configured git credentials for ${insteadOfUrl}`);
60+
// Configure multiple URL patterns to catch all variations
61+
const patterns = [
62+
// Most important: the proxy server itself (this is what's asking for auth)
63+
{
64+
insteadOf: `${baseUrlParsed.protocol}//${baseUrlParsed.host}`,
65+
credUrl: `${baseUrlParsed.protocol}//${testConfig.gitUsername}:${testConfig.gitPassword}@${baseUrlParsed.host}`,
66+
},
67+
// Base URL with trailing slash
68+
{
69+
insteadOf: testConfig.gitProxyBaseUrl,
70+
credUrl: `${baseUrlParsed.protocol}//${testConfig.gitUsername}:${testConfig.gitPassword}@${baseUrlParsed.host}${baseUrlParsed.pathname}`,
71+
},
72+
// Base URL without trailing slash
73+
{
74+
insteadOf: testConfig.gitProxyBaseUrl.replace(/\/$/, ''),
75+
credUrl: `${baseUrlParsed.protocol}//${testConfig.gitUsername}:${testConfig.gitPassword}@${baseUrlParsed.host}`,
76+
},
77+
];
78+
79+
for (const pattern of patterns) {
80+
execSync(`git config url."${pattern.credUrl}".insteadOf "${pattern.insteadOf}"`, {
81+
cwd: tempDir,
82+
encoding: 'utf8',
83+
});
84+
}
85+
} catch (error) {
86+
console.error('Failed to configure git credentials:', error);
87+
throw error;
88+
}
4189
}
4290

4391
export async function waitForService(
@@ -78,9 +126,9 @@ beforeAll(async () => {
78126
console.log(`Git Username: ${testConfig.gitUsername}`);
79127
console.log(`Git Proxy Base URL: ${testConfig.gitProxyBaseUrl}`);
80128

81-
// Wait for the git proxy service to be ready
129+
// Wait for the git proxy UI service to be ready
82130
// Note: Docker Compose should be started externally (e.g., in CI or manually)
83-
await waitForService(`${testConfig.gitProxyUrl}/health`);
131+
await waitForService(`${testConfig.gitProxyUiUrl}/api/v1/healthcheck`);
84132

85133
console.log('E2E test environment is ready');
86134
}, testConfig.timeout);

0 commit comments

Comments
 (0)