chore(opencode-sandbox): add SSH config, git safe directory, and test setup
This commit is contained in:
@@ -10,6 +10,10 @@ RUN pacman -Syu --noconfirm && \
|
|||||||
opencode \
|
opencode \
|
||||||
&& pacman -Scc --noconfirm
|
&& pacman -Scc --noconfirm
|
||||||
|
|
||||||
|
# Git safe directory system-wide config
|
||||||
|
RUN git config --system --add safe.directory /workspace
|
||||||
|
RUN git config --system --add safe.directory '*'
|
||||||
|
|
||||||
# Firewall script — blocks everything except your Gitea instance
|
# Firewall script — blocks everything except your Gitea instance
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
RUN chmod +x /entrypoint.sh
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|||||||
@@ -1,6 +1,28 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix SSH directory and key permissions
|
||||||
|
chmod 700 /root/.ssh
|
||||||
chmod 600 /root/.ssh/id_ed25519
|
chmod 600 /root/.ssh/id_ed25519
|
||||||
|
|
||||||
|
# Add Gitea server to known_hosts (suppress errors if network unavailable)
|
||||||
|
ssh-keyscan -H git.processhub.work >> /root/.ssh/known_hosts 2>/dev/null || true
|
||||||
|
|
||||||
|
# Allow outbound SSH to Gitea
|
||||||
|
GITEA_IP=$(getent hosts git.processhub.work | awk '{print $1}' | head -1)
|
||||||
|
if [ -n "$GITEA_IP" ]; then
|
||||||
|
iptables -A OUTPUT -p tcp --dport 22 -d "$GITEA_IP" -j ACCEPT 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure SSH to use the correct key
|
||||||
export GIT_SSH_COMMAND="ssh -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new"
|
export GIT_SSH_COMMAND="ssh -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new"
|
||||||
|
|
||||||
|
# Configure git user
|
||||||
git config --global user.email "gabriel.pereira@protonmail.com"
|
git config --global user.email "gabriel.pereira@protonmail.com"
|
||||||
git config --global user.name "gabspereira"
|
git config --global user.name "gabspereira"
|
||||||
|
|
||||||
|
# Configure git safe directory (system-wide + workspace specific)
|
||||||
|
git config --system --add safe.directory '*'
|
||||||
|
git config --global --add safe.directory /workspace
|
||||||
|
|
||||||
|
# Run opencode
|
||||||
exec opencode
|
exec opencode
|
||||||
|
|||||||
8
.opencode-sandbox/jest.config.js
Normal file
8
.opencode-sandbox/jest.config.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
rootDir: '.',
|
||||||
|
testMatch: ['**/tests/**/*.test.ts'],
|
||||||
|
verbose: true,
|
||||||
|
forceExit: true,
|
||||||
|
}
|
||||||
17
.opencode-sandbox/package.json
Normal file
17
.opencode-sandbox/package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "opencode-sandbox",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
|
"test:coverage": "jest --coverage"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "29.5.12",
|
||||||
|
"@types/node": "20.11.0",
|
||||||
|
"jest": "29.7.0",
|
||||||
|
"ts-jest": "29.1.2",
|
||||||
|
"typescript": "5.3.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
84
.opencode-sandbox/tests/ssh.test.ts
Normal file
84
.opencode-sandbox/tests/ssh.test.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { exec } from 'child_process'
|
||||||
|
import { promisify } from 'util'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
const execAsync = promisify(exec)
|
||||||
|
|
||||||
|
describe('SSH/Gitea Integration', () => {
|
||||||
|
const SSH_DIR = '/root/.ssh'
|
||||||
|
const SSH_KEY = path.join(SSH_DIR, 'id_ed25519')
|
||||||
|
const KNOWN_HOSTS = path.join(SSH_DIR, 'known_hosts')
|
||||||
|
|
||||||
|
describe('SSH Key Setup', () => {
|
||||||
|
test('SSH directory exists', () => {
|
||||||
|
expect(fs.existsSync(SSH_DIR)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('SSH directory has correct permissions (0700)', () => {
|
||||||
|
const stats = fs.statSync(SSH_DIR)
|
||||||
|
const mode = stats.mode & 0o777
|
||||||
|
expect(mode).toBe(0o700)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('SSH key file exists', () => {
|
||||||
|
expect(fs.existsSync(SSH_KEY)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('SSH key has correct permissions (0600)', () => {
|
||||||
|
const stats = fs.statSync(SSH_KEY)
|
||||||
|
const mode = stats.mode & 0o777
|
||||||
|
expect(mode).toBe(0o600)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Gitea Server', () => {
|
||||||
|
test('known_hosts file exists', () => {
|
||||||
|
expect(fs.existsSync(KNOWN_HOSTS)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('known_hosts contains git.processhub.work', () => {
|
||||||
|
const content = fs.readFileSync(KNOWN_HOSTS, 'utf8')
|
||||||
|
expect(content).toContain('git.processhub.work')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Git Configuration', () => {
|
||||||
|
test('git user.email is configured', async () => {
|
||||||
|
const { stdout } = await execAsync('git config --global user.email')
|
||||||
|
expect(stdout.trim()).toBe('gabriel.pereira@protonmail.com')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('git user.name is configured', async () => {
|
||||||
|
const { stdout } = await execAsync('git config --global user.name')
|
||||||
|
expect(stdout.trim()).toBe('gabspereira')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Gitea SSH Connection', () => {
|
||||||
|
test('SSH connection to Gitea succeeds', async () => {
|
||||||
|
try {
|
||||||
|
const { stdout, stderr } = await execAsync(
|
||||||
|
'ssh -T -o ConnectTimeout=10 git@git.processhub.work',
|
||||||
|
{ timeout: 15000 }
|
||||||
|
)
|
||||||
|
const output = stdout + stderr
|
||||||
|
expect(output).toContain('successfully authenticated')
|
||||||
|
} catch (error: any) {
|
||||||
|
const output = error.stdout + error.stderr
|
||||||
|
expect(output).toContain('gabspereira')
|
||||||
|
expect(output).toContain('successfully authenticated')
|
||||||
|
}
|
||||||
|
}, 20000)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Git Remote Access', () => {
|
||||||
|
test('Can access Gitea repository', async () => {
|
||||||
|
const { stdout, stderr } = await execAsync(
|
||||||
|
'git ls-remote git@git.processhub.work:gabspereira/workspace.git HEAD',
|
||||||
|
{ timeout: 15000 }
|
||||||
|
)
|
||||||
|
expect(stdout).toMatch(/[a-f0-9]+\s+HEAD/)
|
||||||
|
}, 20000)
|
||||||
|
})
|
||||||
|
})
|
||||||
15
.opencode-sandbox/tsconfig.json
Normal file
15
.opencode-sandbox/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"module": "commonjs",
|
||||||
|
"lib": ["ES2020"],
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"types": ["node", "jest"]
|
||||||
|
},
|
||||||
|
"include": ["tests/**/*"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user