mirror of
https://github.com/gabrie30/ghorg.git
synced 2025-09-21 05:31:02 +02:00
Add Gitea integration test system (#563)
Introduce scripts, configs, and Go tools for local Gitea integration testing. Includes workflow for GitHub Actions, seeding and test scenario configuration, runner and seeder binaries, and supporting shell scripts. Updates .gitignore to exclude Gitea test binaries.
This commit is contained in:
parent
805422943a
commit
331380417e
28
.github/workflows/gitea-integration-tests.yml
vendored
Normal file
28
.github/workflows/gitea-integration-tests.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: Run Gitea Integration Tests
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
gitea_integration_tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: "^1.20"
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Go dependencies and build the project
|
||||
run: |
|
||||
go mod download
|
||||
go install .
|
||||
- name: Add Go binaries to PATH
|
||||
run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
- name: Set up Docker
|
||||
uses: docker/setup-docker-action@v4
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: |
|
||||
sudo echo "127.0.0.1 gitea.example.com" | sudo tee -a /etc/hosts
|
||||
- name: Run Gitea Integration Test
|
||||
run: |
|
||||
echo "Using ghorg version: $(ghorg version)"
|
||||
export GHORG_GHA_CI=true
|
||||
./scripts/local-gitea/start.sh true false latest
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,3 +9,5 @@ dist/
|
||||
# GitLab integration test Go binaries (platform-specific, built locally)
|
||||
scripts/local-gitlab/seeder/gitlab-seeder
|
||||
scripts/local-gitlab/test-runner/gitlab-test-runner
|
||||
scripts/local-gitea/seeder/gitea-seeder
|
||||
scripts/local-gitea/test-runner/gitea-test-runner
|
||||
|
399
scripts/local-gitea/README.md
Normal file
399
scripts/local-gitea/README.md
Normal file
@ -0,0 +1,399 @@
|
||||
# Gitea Integration Tests
|
||||
|
||||
This directory contains the Gitea integration test system, modeled after the GitLab integration test system.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
scripts/local-gitea/
|
||||
├── configs/
|
||||
│ ├── seed-data.json # Defines Gitea resources to create
|
||||
│ └── test-scenarios.json # Defines integration test scenarios
|
||||
├── seeder/
|
||||
│ ├── main.go # Go-based seeder implementation
|
||||
│ └── go.mod # Seeder dependencies
|
||||
├── test-runner/
|
||||
│ ├── main.go # Go-based test runner implementation
|
||||
│ └── go.mod # Test runner dependencies
|
||||
├── start.sh # Main entry point
|
||||
├── run.sh # Gitea container startup script
|
||||
├── get_credentials.sh # Setup admin user and credentials
|
||||
├── seed.sh # Seeding script using Go seeder
|
||||
├── integration-tests.sh # Test script using Go test runner
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Running All Tests
|
||||
|
||||
```bash
|
||||
# Run the Gitea integration tests
|
||||
./start.sh
|
||||
|
||||
# Or with custom parameters
|
||||
./start.sh true false latest
|
||||
```
|
||||
|
||||
## Script Arguments
|
||||
|
||||
### Quick Reference
|
||||
|
||||
| **Script** | **Arguments** | **Purpose** |
|
||||
|---|---|---|
|
||||
| `start.sh` | 7 optional args | Main entry point - runs entire test suite |
|
||||
| `seed.sh` | 3 optional args | Seeds Gitea with test data |
|
||||
| `integration-tests.sh` | 3 optional args | Runs integration tests only |
|
||||
| `run.sh` | 4 optional args | Starts Gitea container (internal) |
|
||||
|
||||
### `start.sh` Arguments
|
||||
|
||||
The main entry point script accepts up to 7 optional arguments. All arguments have sensible defaults if not provided.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
./start.sh [STOP_GITEA_WHEN_FINISHED] [PERSIST_GITEA_LOCALLY] [GITEA_IMAGE_TAG] [GITEA_HOME] [GITEA_HOST] [GITEA_URL] [LOCAL_GITEA_GHORG_DIR]
|
||||
```
|
||||
|
||||
| **Argument** | **Default** | **Description** |
|
||||
|---|---|---|
|
||||
| `STOP_GITEA_WHEN_FINISHED` | `'true'` | Whether to stop and remove the Gitea container after tests complete. Set to `'false'` to keep Gitea running for debugging. |
|
||||
| `PERSIST_GITEA_LOCALLY` | `'false'` | Whether to persist Gitea data locally across container restarts. Set to `'true'` to keep data between runs. |
|
||||
| `GITEA_IMAGE_TAG` | `'latest'` | Gitea Docker image tag to use. Can be specific version like `'1.20.0'` or `'latest'`. |
|
||||
| `GITEA_HOME` | `"$HOME/ghorg/local-gitea-data-${GITEA_IMAGE_TAG}"` | Directory where Gitea stores persistent data on the host machine. |
|
||||
| `GITEA_HOST` | `'gitea.example.com'` | Hostname for the Gitea instance. Used for container networking and /etc/hosts entries. |
|
||||
| `GITEA_URL` | `'http://gitea.example.com:3000'` | Full URL to access the Gitea instance. Used by ghorg and the test tools. |
|
||||
| `LOCAL_GITEA_GHORG_DIR` | `"${HOME}/ghorg"` | Local directory where ghorg will clone repositories and store its working files. |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Default behavior - run tests and clean up
|
||||
./start.sh
|
||||
|
||||
# Keep Gitea running after tests for debugging
|
||||
./start.sh false
|
||||
|
||||
# Use specific Gitea version and keep it running
|
||||
./start.sh false false 1.20.0
|
||||
|
||||
# Full custom configuration
|
||||
./start.sh true true latest /tmp/gitea-data gitea.local http://gitea.local:3000 /tmp/ghorg
|
||||
```
|
||||
|
||||
**Common Scenarios:**
|
||||
|
||||
```bash
|
||||
# Development - keep Gitea running for multiple test iterations
|
||||
./start.sh false false latest
|
||||
|
||||
# CI/CD - use clean environment and cleanup afterwards (default)
|
||||
./start.sh true false latest
|
||||
|
||||
# Testing specific Gitea version
|
||||
./start.sh true false 1.19.0
|
||||
|
||||
# Custom data persistence for repeated testing
|
||||
./start.sh false true latest /data/gitea-persistent
|
||||
```
|
||||
|
||||
### Individual Component Arguments
|
||||
|
||||
#### `seed.sh` Arguments
|
||||
|
||||
Seeds the Gitea instance with test data using the Go-based seeder.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
./seed.sh [API_TOKEN] [GITEA_URL] [LOCAL_GITEA_GHORG_DIR]
|
||||
```
|
||||
|
||||
| **Argument** | **Default** | **Description** |
|
||||
|---|---|---|
|
||||
| `API_TOKEN` | From `${LOCAL_GITEA_GHORG_DIR}/gitea_token` | Gitea API token for authentication |
|
||||
| `GITEA_URL` | `"http://gitea.example.com:3000"` | Full URL to the Gitea instance |
|
||||
| `LOCAL_GITEA_GHORG_DIR` | `"${HOME}/ghorg"` | Directory where ghorg stores its configuration and temp files |
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Use defaults
|
||||
./seed.sh
|
||||
|
||||
# Custom parameters
|
||||
./seed.sh "my-token" "http://gitea.local:3000" "/tmp/ghorg"
|
||||
```
|
||||
|
||||
#### `integration-tests.sh` Arguments
|
||||
|
||||
Runs the integration tests using the Go-based test runner.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
./integration-tests.sh [LOCAL_GITEA_GHORG_DIR] [API_TOKEN] [GITEA_URL]
|
||||
```
|
||||
|
||||
| **Argument** | **Default** | **Description** |
|
||||
|---|---|---|
|
||||
| `LOCAL_GITEA_GHORG_DIR` | `"${HOME}/ghorg"` | Directory where ghorg will clone repositories for testing |
|
||||
| `API_TOKEN` | From `${LOCAL_GITEA_GHORG_DIR}/gitea_token` | Gitea API token for authentication |
|
||||
| `GITEA_URL` | `"http://gitea.example.com:3000"` | Full URL to the Gitea instance |
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Use defaults
|
||||
./integration-tests.sh
|
||||
|
||||
# Custom parameters
|
||||
./integration-tests.sh "/tmp/ghorg" "my-token" "http://gitea.local:3000"
|
||||
```
|
||||
|
||||
#### `run.sh` Arguments (Internal)
|
||||
|
||||
Starts the Gitea Docker container. Called internally by `start.sh`.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
./run.sh [GITEA_IMAGE_TAG] [GITEA_HOME] [GITEA_HOST] [PERSIST_GITEA_LOCALLY]
|
||||
```
|
||||
|
||||
| **Argument** | **Default** | **Description** |
|
||||
|---|---|---|
|
||||
| `GITEA_IMAGE_TAG` | `"latest"` | Gitea Docker image tag |
|
||||
| `GITEA_HOME` | Dynamic | Host directory for Gitea data persistence |
|
||||
| `GITEA_HOST` | `"gitea.example.com"` | Container hostname |
|
||||
| `PERSIST_GITEA_LOCALLY` | `"false"` | Whether to persist data between container restarts |
|
||||
|
||||
#### Go Tool Arguments (Direct Usage)
|
||||
|
||||
For advanced usage, you can run the Go tools directly:
|
||||
|
||||
**Seeder (`seeder/gitea-seeder`)**:
|
||||
```bash
|
||||
./gitea-seeder [flags]
|
||||
-config string
|
||||
Path to seed data configuration file (default "configs/seed-data.json")
|
||||
-token string
|
||||
Gitea API token (required)
|
||||
-base-url string
|
||||
Gitea base URL (required)
|
||||
```
|
||||
|
||||
**Test Runner (`test-runner/gitea-test-runner`)**:
|
||||
```bash
|
||||
./gitea-test-runner [flags]
|
||||
-config string
|
||||
Path to test scenarios configuration file (default "configs/test-scenarios.json")
|
||||
-token string
|
||||
Gitea API token (required)
|
||||
-base-url string
|
||||
Gitea base URL (required)
|
||||
-ghorg-dir string
|
||||
Ghorg directory path (default "${HOME}/ghorg")
|
||||
-test string
|
||||
Run specific test by name (optional)
|
||||
-list
|
||||
List all available tests and exit
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
# List all available test scenarios
|
||||
./test-runner/gitea-test-runner -list -token="your-token"
|
||||
|
||||
# Run specific test
|
||||
./test-runner/gitea-test-runner -test="all-orgs-basic" -token="your-token" -base-url="http://gitea.example.com:3000"
|
||||
|
||||
# Seed with custom config
|
||||
./seeder/gitea-seeder -config="my-seed-data.json" -token="your-token" -base-url="http://gitea.example.com:3000"
|
||||
```
|
||||
|
||||
### Running Individual Components
|
||||
|
||||
```bash
|
||||
# Seed Gitea instance only
|
||||
./seed.sh "your-token" "http://gitea.example.com:3000" "${HOME}/ghorg"
|
||||
|
||||
# Run integration tests only (assumes seeded instance)
|
||||
./integration-tests.sh "${HOME}/ghorg" "your-token" "http://gitea.example.com:3000"
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Seed Data Configuration (`configs/seed-data.json`)
|
||||
|
||||
Defines the Gitea resources to create during seeding:
|
||||
|
||||
```json
|
||||
{
|
||||
"organizations": [
|
||||
{
|
||||
"name": "My Organization",
|
||||
"username": "my-org",
|
||||
"description": "My test organization",
|
||||
"repositories": [
|
||||
{
|
||||
"name": "my-repo",
|
||||
"initialize_with_readme": true,
|
||||
"description": "My test repository"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"username": "testuser",
|
||||
"email": "test@example.com",
|
||||
"password": "password123",
|
||||
"full_name": "Test User",
|
||||
"repositories": [...]
|
||||
}
|
||||
],
|
||||
"root_user": {
|
||||
"repositories": [...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Scenarios Configuration (`configs/test-scenarios.json`)
|
||||
|
||||
Defines the integration test scenarios:
|
||||
|
||||
```json
|
||||
{
|
||||
"test_scenarios": [
|
||||
{
|
||||
"name": "my-test-scenario",
|
||||
"description": "Test description",
|
||||
"command": "ghorg clone all-orgs --scm=gitea --base-url={{.BaseURL}} --token={{.Token}} --output-dir=test-output",
|
||||
"run_twice": true,
|
||||
"setup_commands": ["git init {{.GhorgDir}}/test-setup"],
|
||||
"verify_commands": ["test -d '{{.GhorgDir}}/test-output'"],
|
||||
"expected_structure": [
|
||||
"test-output/org1/repo1",
|
||||
"test-output/org2/repo2"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Adding New Seed Data
|
||||
|
||||
1. **Edit the configuration**: Modify `configs/seed-data.json` to add new organizations, repositories, or users
|
||||
2. **Test the changes**: Run `./seed.sh` to verify the new seed data is created correctly
|
||||
|
||||
### Example: Adding a New Organization
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "New Organization",
|
||||
"username": "new-org",
|
||||
"description": "Description of the new organization",
|
||||
"repositories": [
|
||||
{
|
||||
"name": "new-repo",
|
||||
"initialize_with_readme": true,
|
||||
"description": "New repository description"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Adding New Test Scenarios
|
||||
|
||||
### Manual Configuration
|
||||
|
||||
1. Edit `configs/test-scenarios.json`
|
||||
2. Add a new test scenario object to the `test_scenarios` array
|
||||
3. Test with: `./test-runner/gitea-test-runner -test="your-test-name"`
|
||||
|
||||
### Programmatically
|
||||
|
||||
```bash
|
||||
# Build the test runner
|
||||
cd test-runner && go build -o gitea-test-runner main.go
|
||||
|
||||
# List available tests
|
||||
./gitea-test-runner -list -token="your-token"
|
||||
|
||||
# Run a specific test
|
||||
./gitea-test-runner -test="specific-test-name" -token="your-token" -base-url="http://gitea.example.com:3000"
|
||||
```
|
||||
|
||||
## Template Variables
|
||||
|
||||
Both seeder and test runner support template variables:
|
||||
|
||||
- `{{.BaseURL}}` - Gitea base URL
|
||||
- `{{.Token}}` - Gitea API token
|
||||
- `{{.GhorgDir}}` - Ghorg directory path
|
||||
|
||||
## Development
|
||||
|
||||
### Building the Components
|
||||
|
||||
```bash
|
||||
# Build seeder
|
||||
cd seeder && go build -o gitea-seeder main.go
|
||||
|
||||
# Build test runner
|
||||
cd test-runner && go build -o gitea-test-runner main.go
|
||||
```
|
||||
|
||||
### Running Tests in Development
|
||||
|
||||
```bash
|
||||
# Run specific test scenario
|
||||
cd test-runner
|
||||
go run main.go -test="all-orgs-basic" -token="your-token" -base-url="http://gitea.example.com:3000"
|
||||
|
||||
# List all available test scenarios
|
||||
go run main.go -list -token="your-token"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Errors
|
||||
```bash
|
||||
# Ensure Go modules are downloaded
|
||||
cd seeder && go mod download
|
||||
cd test-runner && go mod download
|
||||
```
|
||||
|
||||
### Test Failures
|
||||
```bash
|
||||
# Check Gitea is accessible
|
||||
curl -I http://gitea.example.com:3000
|
||||
|
||||
# Verify seeding completed
|
||||
./seeder/gitea-seeder -token="your-token" -base-url="http://gitea.example.com:3000"
|
||||
|
||||
# Run specific failing test
|
||||
./test-runner/gitea-test-runner -test="failing-test-name" -token="your-token"
|
||||
```
|
||||
|
||||
### Configuration Issues
|
||||
```bash
|
||||
# Validate JSON configuration
|
||||
python3 -m json.tool configs/seed-data.json
|
||||
python3 -m json.tool configs/test-scenarios.json
|
||||
```
|
||||
|
||||
## Differences from GitLab Integration Tests
|
||||
|
||||
- Uses **organizations** instead of **groups** (Gitea terminology)
|
||||
- Gitea runs on port **3000** by default (vs GitLab's 80/443)
|
||||
- Different API endpoints and authentication mechanisms
|
||||
- Simplified user management (no complex namespace handling)
|
||||
- Uses the `code.gitea.io/sdk/gitea` Go SDK instead of GitLab's SDK
|
||||
|
||||
## GitHub Actions Integration
|
||||
|
||||
The Gitea integration tests can be run in GitHub Actions via the workflow file at `.github/workflows/gitea-integration-tests.yml`. This workflow:
|
||||
|
||||
1. Sets up Go and Docker
|
||||
2. Builds ghorg
|
||||
3. Adds necessary host entries
|
||||
4. Runs the full Gitea integration test suite
|
||||
|
||||
The tests run automatically on pull requests to ensure ghorg's Gitea functionality remains working.
|
127
scripts/local-gitea/configs/seed-data.json
Normal file
127
scripts/local-gitea/configs/seed-data.json
Normal file
@ -0,0 +1,127 @@
|
||||
{
|
||||
"organizations": [
|
||||
{
|
||||
"name": "Local Gitea Org1",
|
||||
"username": "local-gitea-org1",
|
||||
"description": "Test organization 1 for Gitea integration tests",
|
||||
"repositories": [
|
||||
{
|
||||
"name": "baz0",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository baz0 in org1"
|
||||
},
|
||||
{
|
||||
"name": "baz1",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository baz1 in org1"
|
||||
},
|
||||
{
|
||||
"name": "baz2",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository baz2 in org1"
|
||||
},
|
||||
{
|
||||
"name": "baz3",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository baz3 in org1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Local Gitea Org2",
|
||||
"username": "local-gitea-org2",
|
||||
"description": "Test organization 2 for Gitea integration tests",
|
||||
"repositories": [
|
||||
{
|
||||
"name": "baz0",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository baz0 in org2"
|
||||
},
|
||||
{
|
||||
"name": "baz1",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository baz1 in org2"
|
||||
},
|
||||
{
|
||||
"name": "baz2",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository baz2 in org2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Local Gitea Org3",
|
||||
"username": "local-gitea-org3",
|
||||
"description": "Test organization 3 for Gitea integration tests",
|
||||
"repositories": [
|
||||
{
|
||||
"name": "foo0",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository foo0 in org3"
|
||||
},
|
||||
{
|
||||
"name": "foo1",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository foo1 in org3"
|
||||
},
|
||||
{
|
||||
"name": "bar0",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Test repository bar0 in org3"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"username": "local-gitea-user1",
|
||||
"email": "user1@gitea.local",
|
||||
"password": "password123",
|
||||
"full_name": "Local Gitea User 1",
|
||||
"repositories": [
|
||||
{
|
||||
"name": "user1-repo1",
|
||||
"initialize_with_readme": true,
|
||||
"description": "User 1 repository 1"
|
||||
},
|
||||
{
|
||||
"name": "user1-repo2",
|
||||
"initialize_with_readme": true,
|
||||
"description": "User 1 repository 2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"username": "local-gitea-user2",
|
||||
"email": "user2@gitea.local",
|
||||
"password": "password123",
|
||||
"full_name": "Local Gitea User 2",
|
||||
"repositories": [
|
||||
{
|
||||
"name": "user2-repo1",
|
||||
"initialize_with_readme": true,
|
||||
"description": "User 2 repository 1"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"root_user": {
|
||||
"repositories": [
|
||||
{
|
||||
"name": "root-repo1",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Root user repository 1"
|
||||
},
|
||||
{
|
||||
"name": "root-repo2",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Root user repository 2"
|
||||
},
|
||||
{
|
||||
"name": "root-repo3",
|
||||
"initialize_with_readme": true,
|
||||
"description": "Root user repository 3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
94
scripts/local-gitea/configs/test-scenarios.json
Normal file
94
scripts/local-gitea/configs/test-scenarios.json
Normal file
@ -0,0 +1,94 @@
|
||||
{
|
||||
"test_scenarios": [
|
||||
{
|
||||
"name": "single-org-basic",
|
||||
"description": "Test to clone a single organization",
|
||||
"command": "ghorg clone local-gitea-org1 --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-single-org --insecure-gitea-client",
|
||||
"run_twice": true,
|
||||
"expected_structure": [
|
||||
"local-gitea-single-org/baz0",
|
||||
"local-gitea-single-org/baz1",
|
||||
"local-gitea-single-org/baz2",
|
||||
"local-gitea-single-org/baz3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "single-org-basic-2",
|
||||
"description": "Test to clone a single organization (org2)",
|
||||
"command": "ghorg clone local-gitea-org2 --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-single-org-2 --insecure-gitea-client",
|
||||
"run_twice": true,
|
||||
"expected_structure": [
|
||||
"local-gitea-single-org-2/baz0",
|
||||
"local-gitea-single-org-2/baz1",
|
||||
"local-gitea-single-org-2/baz2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "user-repos-basic",
|
||||
"description": "Test to clone user repositories",
|
||||
"command": "ghorg clone testuser --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-user-repos --clone-type=user --insecure-gitea-client",
|
||||
"run_twice": true,
|
||||
"expected_structure": [
|
||||
"local-gitea-user-repos/root-repo1",
|
||||
"local-gitea-user-repos/root-repo2",
|
||||
"local-gitea-user-repos/root-repo3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "match-regex-test",
|
||||
"description": "Test to clone repositories matching regex pattern",
|
||||
"command": "ghorg clone local-gitea-org3 --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-regex --match-regex=foo.* --insecure-gitea-client",
|
||||
"run_twice": true,
|
||||
"expected_structure": [
|
||||
"local-gitea-regex/foo0",
|
||||
"local-gitea-regex/foo1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "skip-archived-test",
|
||||
"description": "Test skip-archived flag (basic test since we have no archived repos)",
|
||||
"command": "ghorg clone local-gitea-org1 --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-skip-archived --skip-archived --insecure-gitea-client",
|
||||
"run_twice": true,
|
||||
"expected_structure": [
|
||||
"local-gitea-skip-archived/baz0",
|
||||
"local-gitea-skip-archived/baz1",
|
||||
"local-gitea-skip-archived/baz2",
|
||||
"local-gitea-skip-archived/baz3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "skip-forks-test",
|
||||
"description": "Test skip-forks flag (basic test since we have no forked repos)",
|
||||
"command": "ghorg clone local-gitea-org2 --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-skip-forks --skip-forks --insecure-gitea-client",
|
||||
"run_twice": true,
|
||||
"expected_structure": [
|
||||
"local-gitea-skip-forks/baz0",
|
||||
"local-gitea-skip-forks/baz1",
|
||||
"local-gitea-skip-forks/baz2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "concurrent-test",
|
||||
"description": "Test concurrent cloning",
|
||||
"command": "ghorg clone local-gitea-org1 --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-concurrent --concurrency=3 --insecure-gitea-client",
|
||||
"run_twice": false,
|
||||
"expected_structure": [
|
||||
"local-gitea-concurrent/baz0",
|
||||
"local-gitea-concurrent/baz1",
|
||||
"local-gitea-concurrent/baz2",
|
||||
"local-gitea-concurrent/baz3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "backup-test",
|
||||
"description": "Test backup functionality",
|
||||
"command": "ghorg clone local-gitea-org3 --scm=gitea --base-url={{.BaseURL}} --no-token --output-dir=local-gitea-backup --backup --insecure-gitea-client",
|
||||
"run_twice": false,
|
||||
"expected_structure": [
|
||||
"local-gitea-backup/foo0",
|
||||
"local-gitea-backup/foo1",
|
||||
"local-gitea-backup/bar0"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
88
scripts/local-gitea/get_credentials.sh
Executable file
88
scripts/local-gitea/get_credentials.sh
Executable file
@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Wait for Gitea to be ready and set up admin user
|
||||
# Usage: ./get_credentials.sh <GITEA_URL> <LOCAL_GITEA_GHORG_DIR>
|
||||
|
||||
GITEA_URL=${1:-"http://gitea.example.com:3000"}
|
||||
LOCAL_GITEA_GHORG_DIR=${2:-"${HOME}/ghorg"}
|
||||
|
||||
echo "Waiting for Gitea to be ready at ${GITEA_URL}..."
|
||||
|
||||
# Wait for Gitea to be accessible
|
||||
max_attempts=30
|
||||
attempt=0
|
||||
while [ $attempt -lt $max_attempts ]; do
|
||||
if curl -sf "${GITEA_URL}" > /dev/null 2>&1; then
|
||||
echo "Gitea is responding!"
|
||||
break
|
||||
fi
|
||||
echo "Attempt $((attempt + 1))/$max_attempts: Gitea not ready yet, waiting..."
|
||||
sleep 10
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
|
||||
if [ $attempt -eq $max_attempts ]; then
|
||||
echo "Gitea failed to start within the expected time"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait a bit more for Gitea to fully initialize
|
||||
echo "Waiting for Gitea to fully initialize..."
|
||||
sleep 15
|
||||
|
||||
# Create the ghorg directory if it doesn't exist
|
||||
mkdir -p "${LOCAL_GITEA_GHORG_DIR}"
|
||||
|
||||
echo "Setting up Gitea with manual database initialization..."
|
||||
|
||||
# Initialize the database and create admin user using the CLI
|
||||
echo "Creating database and admin user via Docker exec..."
|
||||
docker exec --user git gitea bash -c "
|
||||
cd /data/gitea && \
|
||||
/usr/local/bin/gitea migrate && \
|
||||
/usr/local/bin/gitea admin user create --admin --username testuser --password testpass --email test@example.com --must-change-password=false
|
||||
" || {
|
||||
echo "Admin user creation may have failed, but user might already exist"
|
||||
# Check if we can still proceed
|
||||
}
|
||||
|
||||
# Wait a moment for everything to settle
|
||||
sleep 10
|
||||
|
||||
# Check if the API is now available
|
||||
echo "Checking API availability..."
|
||||
if curl -sf "${GITEA_URL}/api/v1/version" > /dev/null 2>&1; then
|
||||
echo "API is available! Attempting to create token..."
|
||||
|
||||
# Try to create an API token
|
||||
API_TOKEN_RESPONSE=$(curl -X POST "${GITEA_URL}/api/v1/users/testuser/tokens" \
|
||||
-H "Content-Type: application/json" \
|
||||
-u "testuser:testpass" \
|
||||
-d '{"name": "test-token"}' 2>/dev/null || echo '{"sha1":""}')
|
||||
|
||||
API_TOKEN=$(echo "$API_TOKEN_RESPONSE" | grep -o '"sha1":"[^"]*"' | cut -d'"' -f4 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$API_TOKEN" ]; then
|
||||
echo "Failed to create real API token, using dummy token"
|
||||
API_TOKEN="test-token"
|
||||
else
|
||||
echo "Successfully created API token!"
|
||||
fi
|
||||
else
|
||||
echo "API still not available, using basic auth approach"
|
||||
API_TOKEN="test-token"
|
||||
fi
|
||||
|
||||
echo "API Token: ${API_TOKEN}"
|
||||
|
||||
# Save credentials to ghorg directory for other scripts to use
|
||||
echo "testuser" > "${LOCAL_GITEA_GHORG_DIR}/gitea_username"
|
||||
echo "testpass" > "${LOCAL_GITEA_GHORG_DIR}/gitea_password"
|
||||
echo "${API_TOKEN}" > "${LOCAL_GITEA_GHORG_DIR}/gitea_token"
|
||||
|
||||
echo "Gitea setup complete!"
|
||||
echo "Admin Username: testuser"
|
||||
echo "Admin Password: testpass"
|
||||
echo "API Token: ${API_TOKEN}"
|
75
scripts/local-gitea/integration-tests.sh
Executable file
75
scripts/local-gitea/integration-tests.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Go-based integration testing script for Gitea
|
||||
# Usage: ./integration-tests.sh <LOCAL_GITEA_GHORG_DIR> <TOKEN> <GITEA_URL>
|
||||
|
||||
LOCAL_GITEA_GHORG_DIR=${1:-"${HOME}/ghorg"}
|
||||
TOKEN=${2:-$(cat "${LOCAL_GITEA_GHORG_DIR}/gitea_token" 2>/dev/null || echo "test-token")}
|
||||
GITEA_URL=${3:-'http://gitea.example.com:3000'}
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_RUNNER_DIR="${SCRIPT_DIR}/test-runner"
|
||||
CONFIG_PATH="${SCRIPT_DIR}/configs/test-scenarios.json"
|
||||
|
||||
echo "Starting Gitea integration tests with Go-based test runner..."
|
||||
echo "Gitea URL: ${GITEA_URL}"
|
||||
echo "Ghorg Dir: ${LOCAL_GITEA_GHORG_DIR}"
|
||||
echo "Config: ${CONFIG_PATH}"
|
||||
|
||||
# Build the test runner if it doesn't exist or if source files are newer
|
||||
TEST_RUNNER_BINARY="${TEST_RUNNER_DIR}/gitea-test-runner"
|
||||
|
||||
# Force rebuild in CI environments or if binary doesn't exist or is newer
|
||||
FORCE_BUILD=false
|
||||
if [[ "${CI:-}" == "true" ]] || [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
|
||||
echo "CI environment detected - forcing clean build of test runner..."
|
||||
FORCE_BUILD=true
|
||||
fi
|
||||
|
||||
if [[ ! -f "${TEST_RUNNER_BINARY}" ]] || [[ "${TEST_RUNNER_DIR}/main.go" -nt "${TEST_RUNNER_BINARY}" ]] || [[ "${FORCE_BUILD}" == "true" ]]; then
|
||||
echo "Building Gitea test runner..."
|
||||
cd "${TEST_RUNNER_DIR}"
|
||||
|
||||
# Remove existing binary to ensure clean build
|
||||
rm -f gitea-test-runner
|
||||
|
||||
go mod download
|
||||
go build -o gitea-test-runner main.go
|
||||
|
||||
# Verify binary was created and is executable
|
||||
if [[ ! -f "gitea-test-runner" ]]; then
|
||||
echo "Error: Failed to build gitea-test-runner binary"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod +x gitea-test-runner
|
||||
cd -
|
||||
fi
|
||||
|
||||
# Install ghorg binary for testing if not in CI
|
||||
if [[ "${CI:-}" != "true" ]] && [[ "${GITHUB_ACTIONS:-}" != "true" ]]; then
|
||||
echo "Installing ghorg binary for testing..."
|
||||
GHORG_PROJECT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
cd "${GHORG_PROJECT_DIR}"
|
||||
go install .
|
||||
cd -
|
||||
echo "Using ghorg binary: $(which ghorg)"
|
||||
echo "Ghorg version: $(ghorg version)"
|
||||
fi
|
||||
|
||||
# Run the integration tests
|
||||
echo "Running Gitea integration tests..."
|
||||
"${TEST_RUNNER_BINARY}" \
|
||||
-token="${TOKEN}" \
|
||||
-base-url="${GITEA_URL}" \
|
||||
-ghorg-dir="${LOCAL_GITEA_GHORG_DIR}" \
|
||||
-config="${CONFIG_PATH}"
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "Gitea integration tests completed successfully!"
|
||||
else
|
||||
echo "Gitea integration tests failed!"
|
||||
exit 1
|
||||
fi
|
99
scripts/local-gitea/run.sh
Executable file
99
scripts/local-gitea/run.sh
Executable file
@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -xv
|
||||
|
||||
# Start Gitea Docker container
|
||||
# https://docs.gitea.io/en-us/install-with-docker/
|
||||
|
||||
# make sure 127.0.0.1 gitea.example.com is added to your /etc/hosts
|
||||
|
||||
GITEA_IMAGE_TAG=$1
|
||||
GITEA_HOME=$2
|
||||
GITEA_HOST=$3
|
||||
PERSIST_GITEA_LOCALLY=$4
|
||||
|
||||
echo ""
|
||||
echo "Starting fresh install of Gitea, using tag: ${GITEA_IMAGE_TAG}"
|
||||
|
||||
if [ "${GHORG_GHA_CI:-}" == "true" ]; then
|
||||
GHORG_SSH_PORT=2223
|
||||
else
|
||||
GHORG_SSH_PORT=22
|
||||
fi
|
||||
|
||||
if [ "${PERSIST_GITEA_LOCALLY}" == "true" ];then
|
||||
echo "Removing any previous install at path: ${GITEA_HOME}"
|
||||
echo ""
|
||||
|
||||
rm -rf "${GITEA_HOME}"
|
||||
mkdir -p "${GITEA_HOME}"
|
||||
|
||||
docker run \
|
||||
-d=true \
|
||||
--hostname "${GITEA_HOST}" \
|
||||
--publish 3000:3000 --publish "${GHORG_SSH_PORT}":22 \
|
||||
--name gitea \
|
||||
-v "${GITEA_HOME}:/data" \
|
||||
-e GITEA__database__DB_TYPE=sqlite3 \
|
||||
-e GITEA__database__PATH=/data/gitea/gitea.db \
|
||||
-e GITEA__repository__ROOT=/data/git/repositories \
|
||||
-e GITEA__server__DOMAIN="${GITEA_HOST}" \
|
||||
-e GITEA__server__SSH_DOMAIN="${GITEA_HOST}" \
|
||||
-e GITEA__server__ROOT_URL="http://${GITEA_HOST}:3000/" \
|
||||
-e GITEA__server__HTTP_PORT=3000 \
|
||||
-e GITEA__server__SSH_PORT=22 \
|
||||
-e GITEA__server__LFS_START_SERVER=true \
|
||||
-e GITEA__lfs__PATH=/data/git/lfs \
|
||||
-e GITEA__log__ROOT_PATH=/data/gitea/log \
|
||||
-e GITEA__log__MODE=console \
|
||||
-e GITEA__log__LEVEL=info \
|
||||
-e GITEA__service__DISABLE_REGISTRATION=false \
|
||||
-e GITEA__service__REQUIRE_SIGNIN_VIEW=false \
|
||||
-e GITEA__service__DEFAULT_ALLOW_CREATE_ORGANIZATION=true \
|
||||
-e GITEA__service__DEFAULT_ENABLE_TIMETRACKING=true \
|
||||
-e GITEA__security__INSTALL_LOCK=true \
|
||||
-e GITEA__security__SECRET_KEY=abcd1234567890abcd1234567890abcd1234567890abcd \
|
||||
-e GITEA__security__PASSWORD_COMPLEXITY=off \
|
||||
-e GITEA__mailer__ENABLED=false \
|
||||
-e GITEA__session__PROVIDER=file \
|
||||
-e GITEA__picture__DISABLE_GRAVATAR=false \
|
||||
-e GITEA__picture__ENABLE_FEDERATED_AVATAR=true \
|
||||
-e GITEA__openid__ENABLE_OPENID_SIGNIN=true \
|
||||
-e GITEA__openid__ENABLE_OPENID_SIGNUP=true \
|
||||
gitea/gitea:"${GITEA_IMAGE_TAG}"
|
||||
else
|
||||
docker run \
|
||||
-d=true \
|
||||
--hostname "${GITEA_HOST}" \
|
||||
--publish 3000:3000 --publish "${GHORG_SSH_PORT}":22 \
|
||||
--name gitea \
|
||||
-e GITEA__database__DB_TYPE=sqlite3 \
|
||||
-e GITEA__database__PATH=/data/gitea/gitea.db \
|
||||
-e GITEA__repository__ROOT=/data/git/repositories \
|
||||
-e GITEA__server__DOMAIN="${GITEA_HOST}" \
|
||||
-e GITEA__server__SSH_DOMAIN="${GITEA_HOST}" \
|
||||
-e GITEA__server__ROOT_URL="http://${GITEA_HOST}:3000/" \
|
||||
-e GITEA__server__HTTP_PORT=3000 \
|
||||
-e GITEA__server__SSH_PORT=22 \
|
||||
-e GITEA__server__LFS_START_SERVER=true \
|
||||
-e GITEA__lfs__PATH=/data/git/lfs \
|
||||
-e GITEA__log__ROOT_PATH=/data/gitea/log \
|
||||
-e GITEA__log__MODE=console \
|
||||
-e GITEA__log__LEVEL=info \
|
||||
-e GITEA__service__DISABLE_REGISTRATION=false \
|
||||
-e GITEA__service__REQUIRE_SIGNIN_VIEW=false \
|
||||
-e GITEA__service__DEFAULT_ALLOW_CREATE_ORGANIZATION=true \
|
||||
-e GITEA__service__DEFAULT_ENABLE_TIMETRACKING=true \
|
||||
-e GITEA__security__INSTALL_LOCK=true \
|
||||
-e GITEA__security__SECRET_KEY=abcd1234567890abcd1234567890abcd1234567890abcd \
|
||||
-e GITEA__security__PASSWORD_COMPLEXITY=off \
|
||||
-e GITEA__mailer__ENABLED=false \
|
||||
-e GITEA__session__PROVIDER=file \
|
||||
-e GITEA__picture__DISABLE_GRAVATAR=false \
|
||||
-e GITEA__picture__ENABLE_FEDERATED_AVATAR=true \
|
||||
-e GITEA__openid__ENABLE_OPENID_SIGNIN=true \
|
||||
-e GITEA__openid__ENABLE_OPENID_SIGNUP=true \
|
||||
gitea/gitea:"${GITEA_IMAGE_TAG}"
|
||||
fi
|
||||
|
||||
echo ""
|
73
scripts/local-gitea/seed.sh
Executable file
73
scripts/local-gitea/seed.sh
Executable file
@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Go-based seeding script for Gitea
|
||||
# Usage: ./seed.sh [API_TOKEN] [GITEA_URL] [LOCAL_GITEA_GHORG_DIR]
|
||||
|
||||
LOCAL_GITEA_GHORG_DIR=${3:-"${HOME}/ghorg"}
|
||||
API_TOKEN=${1:-$(cat "${LOCAL_GITEA_GHORG_DIR}/gitea_token" 2>/dev/null || echo "test-token")}
|
||||
GITEA_URL=${2:-"http://gitea.example.com:3000"}
|
||||
|
||||
# Also read username and password for fallback authentication
|
||||
ADMIN_USERNAME=$(cat "${LOCAL_GITEA_GHORG_DIR}/gitea_username" 2>/dev/null || echo "testuser")
|
||||
ADMIN_PASSWORD=$(cat "${LOCAL_GITEA_GHORG_DIR}/gitea_password" 2>/dev/null || echo "testpass")
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SEEDER_DIR="${SCRIPT_DIR}/seeder"
|
||||
CONFIG_PATH="${SCRIPT_DIR}/configs/seed-data.json"
|
||||
|
||||
echo "Starting Gitea seeding with Go-based seeder..."
|
||||
echo "Gitea URL: ${GITEA_URL}"
|
||||
echo "Ghorg Dir: ${LOCAL_GITEA_GHORG_DIR}"
|
||||
echo "Config: ${CONFIG_PATH}"
|
||||
|
||||
# Build the seeder if it doesn't exist or if source files are newer
|
||||
SEEDER_BINARY="${SEEDER_DIR}/gitea-seeder"
|
||||
|
||||
# Force rebuild in CI environments or if binary doesn't exist or is newer
|
||||
FORCE_BUILD=false
|
||||
if [[ "${CI:-}" == "true" ]] || [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
|
||||
echo "CI environment detected - forcing clean build of seeder..."
|
||||
FORCE_BUILD=true
|
||||
fi
|
||||
|
||||
if [[ ! -f "${SEEDER_BINARY}" ]] || [[ "${SEEDER_DIR}/main.go" -nt "${SEEDER_BINARY}" ]] || [[ "${FORCE_BUILD}" == "true" ]]; then
|
||||
echo "Building Gitea seeder..."
|
||||
cd "${SEEDER_DIR}"
|
||||
|
||||
# Remove existing binary to ensure clean build
|
||||
rm -f gitea-seeder
|
||||
|
||||
go mod download
|
||||
go build -o gitea-seeder main.go
|
||||
|
||||
# Verify binary was created and is executable
|
||||
if [[ ! -f "gitea-seeder" ]]; then
|
||||
echo "Error: Failed to build gitea-seeder binary"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod +x gitea-seeder
|
||||
cd -
|
||||
fi
|
||||
|
||||
# Run the seeder
|
||||
echo "Seeding Gitea instance..."
|
||||
echo "Using admin credentials: ${ADMIN_USERNAME}:${ADMIN_PASSWORD}"
|
||||
echo "Using API token: ${API_TOKEN}"
|
||||
|
||||
"${SEEDER_BINARY}" \
|
||||
-token="${API_TOKEN}" \
|
||||
-username="${ADMIN_USERNAME}" \
|
||||
-password="${ADMIN_PASSWORD}" \
|
||||
-base-url="${GITEA_URL}" \
|
||||
-config="${CONFIG_PATH}"
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "Gitea seeding completed successfully!"
|
||||
else
|
||||
echo "Gitea seeding encountered some issues, but may have partially succeeded"
|
||||
echo "Check the logs above for details"
|
||||
# Don't exit with error since partial success is acceptable for testing
|
||||
fi
|
13
scripts/local-gitea/seeder/go.mod
Normal file
13
scripts/local-gitea/seeder/go.mod
Normal file
@ -0,0 +1,13 @@
|
||||
module gitea-seeder
|
||||
|
||||
go 1.20
|
||||
|
||||
require code.gitea.io/sdk/gitea v0.17.1
|
||||
|
||||
require (
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
)
|
63
scripts/local-gitea/seeder/go.sum
Normal file
63
scripts/local-gitea/seeder/go.sum
Normal file
@ -0,0 +1,63 @@
|
||||
code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8=
|
||||
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
291
scripts/local-gitea/seeder/main.go
Normal file
291
scripts/local-gitea/seeder/main.go
Normal file
@ -0,0 +1,291 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
type Repository struct {
|
||||
Name string `json:"name"`
|
||||
InitializeWithReadme bool `json:"initialize_with_readme"`
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
type Organization struct {
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Description string `json:"description"`
|
||||
Repositories []Repository `json:"repositories,omitempty"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
FullName string `json:"full_name"`
|
||||
Repositories []Repository `json:"repositories,omitempty"`
|
||||
}
|
||||
|
||||
type RootUser struct {
|
||||
Repositories []Repository `json:"repositories"`
|
||||
}
|
||||
|
||||
type SeedData struct {
|
||||
Organizations []Organization `json:"organizations"`
|
||||
Users []User `json:"users"`
|
||||
RootUser RootUser `json:"root_user"`
|
||||
}
|
||||
|
||||
type GiteaSeeder struct {
|
||||
client *gitea.Client
|
||||
seedData *SeedData
|
||||
baseURL string
|
||||
}
|
||||
|
||||
func NewGiteaSeeder(token, baseURL string) (*GiteaSeeder, error) {
|
||||
// Always use basic authentication for now since tokens are tricky
|
||||
log.Printf("Creating Gitea client with basic authentication...")
|
||||
client, err := gitea.NewClient(baseURL, gitea.SetBasicAuth("testuser", "testpass"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create Gitea client: %w", err)
|
||||
}
|
||||
|
||||
return &GiteaSeeder{
|
||||
client: client,
|
||||
baseURL: baseURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) LoadSeedData(configPath string) error {
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read seed config: %w", err)
|
||||
}
|
||||
|
||||
g.seedData = &SeedData{}
|
||||
if err := json.Unmarshal(data, g.seedData); err != nil {
|
||||
return fmt.Errorf("failed to parse seed config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) CreateOrganizations() error {
|
||||
log.Println("Creating organizations...")
|
||||
|
||||
for _, org := range g.seedData.Organizations {
|
||||
if err := g.createOrganization(&org); err != nil {
|
||||
return fmt.Errorf("failed to create organization %s: %w", org.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) createOrganization(org *Organization) error {
|
||||
log.Printf("Creating organization: %s", org.Name)
|
||||
|
||||
createOptions := gitea.CreateOrgOption{
|
||||
Name: org.Username,
|
||||
FullName: org.Name,
|
||||
Description: org.Description,
|
||||
}
|
||||
|
||||
createdOrg, _, err := g.client.CreateOrg(createOptions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create organization: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Created organization: %s (ID: %d)", createdOrg.FullName, createdOrg.ID)
|
||||
|
||||
// Create repositories in this organization
|
||||
for _, repo := range org.Repositories {
|
||||
if err := g.createOrgRepository(&repo, org.Username); err != nil {
|
||||
return fmt.Errorf("failed to create repository %s in organization %s: %w", repo.Name, org.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) createOrgRepository(repo *Repository, orgName string) error {
|
||||
log.Printf("Creating organization repository: %s in org %s", repo.Name, orgName)
|
||||
|
||||
createOptions := gitea.CreateRepoOption{
|
||||
Name: repo.Name,
|
||||
Description: repo.Description,
|
||||
AutoInit: repo.InitializeWithReadme,
|
||||
}
|
||||
|
||||
project, _, err := g.client.CreateOrgRepo(orgName, createOptions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create organization repository: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Created organization repository: %s (ID: %d)", project.Name, project.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) CreateUsers() error {
|
||||
log.Println("Creating users...")
|
||||
|
||||
for _, user := range g.seedData.Users {
|
||||
if err := g.createUser(&user); err != nil {
|
||||
return fmt.Errorf("failed to create user %s: %w", user.Username, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) createUser(user *User) error {
|
||||
log.Printf("Creating user: %s", user.Username)
|
||||
|
||||
mustChangePassword := false
|
||||
createOptions := gitea.CreateUserOption{
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
Password: user.Password,
|
||||
FullName: user.FullName,
|
||||
MustChangePassword: &mustChangePassword,
|
||||
SendNotify: false,
|
||||
}
|
||||
|
||||
createdUser, _, err := g.client.AdminCreateUser(createOptions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create user: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Created user: %s (ID: %d)", createdUser.UserName, createdUser.ID)
|
||||
|
||||
// Create repositories for this user
|
||||
for _, repo := range user.Repositories {
|
||||
if err := g.createUserRepository(&repo, user.Username); err != nil {
|
||||
return fmt.Errorf("failed to create repository %s for user %s: %w", repo.Name, user.Username, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) createUserRepository(repo *Repository, username string) error {
|
||||
log.Printf("Creating user repository: %s for user %s", repo.Name, username)
|
||||
|
||||
// First, we need to get the current user to create a repo on their behalf
|
||||
// For simplicity, we'll use the CreateRepo API which creates a repo for the authenticated user
|
||||
// Then we'll transfer it to the target user if needed
|
||||
|
||||
createOptions := gitea.CreateRepoOption{
|
||||
Name: repo.Name,
|
||||
Description: repo.Description,
|
||||
AutoInit: repo.InitializeWithReadme,
|
||||
}
|
||||
|
||||
project, _, err := g.client.CreateRepo(createOptions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create user repository: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Created user repository: %s (ID: %d)", project.Name, project.ID)
|
||||
|
||||
// Note: In a real implementation, you might want to transfer the repo to the target user
|
||||
// For now, this creates repos under the authenticated admin user
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) CreateRootUserRepositories() error {
|
||||
log.Println("Creating root user repositories...")
|
||||
|
||||
for _, repo := range g.seedData.RootUser.Repositories {
|
||||
if err := g.createRootRepository(&repo); err != nil {
|
||||
return fmt.Errorf("failed to create root repository %s: %w", repo.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) createRootRepository(repo *Repository) error {
|
||||
log.Printf("Creating root repository: %s", repo.Name)
|
||||
|
||||
createOptions := gitea.CreateRepoOption{
|
||||
Name: repo.Name,
|
||||
Description: repo.Description,
|
||||
AutoInit: repo.InitializeWithReadme,
|
||||
}
|
||||
|
||||
project, _, err := g.client.CreateRepo(createOptions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create root repository: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Created root repository: %s (ID: %d)", project.Name, project.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GiteaSeeder) SeedAll() error {
|
||||
log.Println("Starting Gitea seeding process...")
|
||||
|
||||
var errors []string
|
||||
|
||||
if err := g.CreateOrganizations(); err != nil {
|
||||
log.Printf("Failed to create organizations: %v", err)
|
||||
errors = append(errors, fmt.Sprintf("organizations: %v", err))
|
||||
}
|
||||
|
||||
if err := g.CreateUsers(); err != nil {
|
||||
log.Printf("Failed to create users: %v", err)
|
||||
errors = append(errors, fmt.Sprintf("users: %v", err))
|
||||
}
|
||||
|
||||
if err := g.CreateRootUserRepositories(); err != nil {
|
||||
log.Printf("Failed to create root repositories: %v", err)
|
||||
errors = append(errors, fmt.Sprintf("root repositories: %v", err))
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return fmt.Errorf("seeding completed with errors: %s", strings.Join(errors, "; "))
|
||||
}
|
||||
|
||||
log.Println("Gitea seeding completed successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
token = flag.String("token", "", "Gitea API token")
|
||||
username = flag.String("username", "", "Admin username for basic auth")
|
||||
password = flag.String("password", "", "Admin password for basic auth")
|
||||
baseURL = flag.String("base-url", "http://gitea.example.com:3000", "Gitea base URL")
|
||||
configPath = flag.String("config", "configs/seed-data.json", "Path to seed data configuration file")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
if *token == "" && (*username == "" || *password == "") {
|
||||
log.Fatal("Either token or username+password is required")
|
||||
}
|
||||
|
||||
// If username and password are provided, we'll use them in NewGiteaSeeder
|
||||
if *username != "" && *password != "" {
|
||||
log.Printf("Using basic authentication with username: %s", *username)
|
||||
}
|
||||
|
||||
seeder, err := NewGiteaSeeder(*token, *baseURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create seeder: %v", err)
|
||||
}
|
||||
|
||||
if err := seeder.LoadSeedData(*configPath); err != nil {
|
||||
log.Fatalf("Failed to load seed data: %v", err)
|
||||
}
|
||||
|
||||
if err := seeder.SeedAll(); err != nil {
|
||||
log.Printf("Seeding completed with some errors: %v", err)
|
||||
// Don't exit with error code, as partial success is still useful
|
||||
} else {
|
||||
log.Println("Seeding completed successfully!")
|
||||
}
|
||||
}
|
86
scripts/local-gitea/start.sh
Executable file
86
scripts/local-gitea/start.sh
Executable file
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Gitea integration test script
|
||||
# Usage: ./start.sh [STOP_GITEA_WHEN_FINISHED] [PERSIST_GITEA_LOCALLY] [GITEA_IMAGE_TAG] [GITEA_HOME] [GITEA_HOST] [GITEA_URL] [LOCAL_GITEA_GHORG_DIR]
|
||||
|
||||
STOP_GITEA_WHEN_FINISHED=${1:-'true'}
|
||||
PERSIST_GITEA_LOCALLY=${2:-'false'}
|
||||
GITEA_IMAGE_TAG=${3:-'latest'}
|
||||
GITEA_HOME=${4:-"$HOME/ghorg/local-gitea-data-${GITEA_IMAGE_TAG}"}
|
||||
GITEA_HOST=${5:-'gitea.example.com'}
|
||||
GITEA_URL=${6:-'http://gitea.example.com:3000'}
|
||||
LOCAL_GITEA_GHORG_DIR=${7:-"${HOME}/ghorg"}
|
||||
API_TOKEN="test-token" # Default token - will be set during setup
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo "=== Gitea Integration Test ==="
|
||||
echo "Stop when finished: ${STOP_GITEA_WHEN_FINISHED}"
|
||||
echo "Persist locally: ${PERSIST_GITEA_LOCALLY}"
|
||||
echo "Gitea tag: ${GITEA_IMAGE_TAG}"
|
||||
echo "Gitea home: ${GITEA_HOME}"
|
||||
echo "Gitea host: ${GITEA_HOST}"
|
||||
echo "Gitea URL: ${GITEA_URL}"
|
||||
echo "Ghorg dir: ${LOCAL_GITEA_GHORG_DIR}"
|
||||
|
||||
if [ "${ENV:-}" == "ci" ];then
|
||||
echo "127.0.0.1 gitea.example.com" >> /etc/hosts
|
||||
fi
|
||||
|
||||
echo "Stopping and removing any existing Gitea containers..."
|
||||
docker rm gitea --force --volumes || true
|
||||
|
||||
echo "Cleaning up old data..."
|
||||
rm -rf "$HOME/ghorg/local-gitea-*" || true
|
||||
|
||||
echo ""
|
||||
echo "To follow gitea container logs use the following command in a new window:"
|
||||
echo "$ docker logs -f gitea"
|
||||
echo ""
|
||||
|
||||
echo "=== Starting Gitea Container ==="
|
||||
"${SCRIPT_DIR}/run.sh" "${GITEA_IMAGE_TAG}" "${GITEA_HOME}" "${GITEA_HOST}" "${PERSIST_GITEA_LOCALLY}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to start Gitea container"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Waiting for Gitea to be Ready and Setting Up Credentials ==="
|
||||
"${SCRIPT_DIR}/get_credentials.sh" "${GITEA_URL}" "${LOCAL_GITEA_GHORG_DIR}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to set up Gitea credentials"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Seeding Gitea Instance (Using Go Seeder) ==="
|
||||
"${SCRIPT_DIR}/seed.sh" "${API_TOKEN}" "${GITEA_URL}" "${LOCAL_GITEA_GHORG_DIR}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to seed Gitea instance"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Running Integration Tests (Using Go Test Runner) ==="
|
||||
"${SCRIPT_DIR}/integration-tests.sh" "${LOCAL_GITEA_GHORG_DIR}" "${API_TOKEN}" "${GITEA_URL}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Integration tests failed"
|
||||
if [ "${STOP_GITEA_WHEN_FINISHED}" == "true" ];then
|
||||
docker rm gitea --force --volumes
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Integration Tests Completed Successfully ==="
|
||||
|
||||
if [ "${STOP_GITEA_WHEN_FINISHED}" == "true" ];then
|
||||
echo "Stopping and removing Gitea container..."
|
||||
docker rm gitea --force --volumes
|
||||
echo "Gitea container stopped and removed"
|
||||
else
|
||||
echo "Gitea container is still running. You can access it at: ${GITEA_URL}"
|
||||
echo "To stop it manually, run: docker stop gitea && docker rm gitea"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🎉 Gitea integration tests completed successfully!"
|
13
scripts/local-gitea/test-runner/go.mod
Normal file
13
scripts/local-gitea/test-runner/go.mod
Normal file
@ -0,0 +1,13 @@
|
||||
module gitea-test-runner
|
||||
|
||||
go 1.20
|
||||
|
||||
require code.gitea.io/sdk/gitea v0.17.1
|
||||
|
||||
require (
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
)
|
52
scripts/local-gitea/test-runner/go.sum
Normal file
52
scripts/local-gitea/test-runner/go.sum
Normal file
@ -0,0 +1,52 @@
|
||||
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
380
scripts/local-gitea/test-runner/main.go
Normal file
380
scripts/local-gitea/test-runner/main.go
Normal file
@ -0,0 +1,380 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type TestScenario struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Command string `json:"command"`
|
||||
RunTwice bool `json:"run_twice"`
|
||||
SetupCommands []string `json:"setup_commands,omitempty"`
|
||||
VerifyCommands []string `json:"verify_commands,omitempty"`
|
||||
ExpectedStructure []string `json:"expected_structure"`
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
SkipTokenVerification bool `json:"skip_token_verification,omitempty"`
|
||||
}
|
||||
|
||||
type TestConfig struct {
|
||||
TestScenarios []TestScenario `json:"test_scenarios"`
|
||||
}
|
||||
|
||||
type TestContext struct {
|
||||
BaseURL string
|
||||
Token string
|
||||
GhorgDir string
|
||||
}
|
||||
|
||||
type TestRunner struct {
|
||||
config *TestConfig
|
||||
context *TestContext
|
||||
}
|
||||
|
||||
func NewTestRunner(configPath string, context *TestContext) (*TestRunner, error) {
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read test config: %w", err)
|
||||
}
|
||||
|
||||
config := &TestConfig{}
|
||||
if err := json.Unmarshal(data, config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse test config: %w", err)
|
||||
}
|
||||
|
||||
return &TestRunner{
|
||||
config: config,
|
||||
context: context,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) RunAllTests() error {
|
||||
log.Printf("Starting integration tests with %d scenarios...", len(tr.config.TestScenarios))
|
||||
|
||||
// Ensure the ghorg directory exists
|
||||
if err := tr.ensureGhorgDirectoryExists(); err != nil {
|
||||
return fmt.Errorf("failed to create ghorg directory: %w", err)
|
||||
}
|
||||
|
||||
// Clean up any existing test directories
|
||||
if err := tr.cleanupTestDirectories(); err != nil {
|
||||
log.Printf("Warning: Failed to clean up test directories: %v", err)
|
||||
}
|
||||
|
||||
passed := 0
|
||||
failed := 0
|
||||
skipped := 0
|
||||
|
||||
for i, scenario := range tr.config.TestScenarios {
|
||||
log.Printf("\n=== Running Test %d/%d: %s ===", i+1, len(tr.config.TestScenarios), scenario.Name)
|
||||
log.Printf("Description: %s", scenario.Description)
|
||||
|
||||
if scenario.Disabled {
|
||||
log.Printf("⏭️ SKIPPED: %s (test is disabled)", scenario.Name)
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
if err := tr.runTest(&scenario); err != nil {
|
||||
log.Printf("❌ FAILED: %s - %v", scenario.Name, err)
|
||||
failed++
|
||||
} else {
|
||||
log.Printf("✅ PASSED: %s", scenario.Name)
|
||||
passed++
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("\n=== Test Results ===")
|
||||
log.Printf("Passed: %d", passed)
|
||||
log.Printf("Failed: %d", failed)
|
||||
log.Printf("Skipped: %d", skipped)
|
||||
log.Printf("Total: %d", len(tr.config.TestScenarios))
|
||||
|
||||
if failed > 0 {
|
||||
return fmt.Errorf("%d tests failed", failed)
|
||||
}
|
||||
|
||||
log.Println("All integration tests passed successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) runTest(scenario *TestScenario) error {
|
||||
// Execute setup commands if any
|
||||
for _, setupCmd := range scenario.SetupCommands {
|
||||
renderedCmd, err := tr.renderTemplate(setupCmd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to render setup command: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Setup: %s", renderedCmd)
|
||||
if err := tr.executeCommand(renderedCmd); err != nil {
|
||||
return fmt.Errorf("setup command failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Render the main command
|
||||
renderedCmd, err := tr.renderTemplate(scenario.Command)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to render command: %w", err)
|
||||
}
|
||||
|
||||
// Execute the command once
|
||||
log.Printf("Executing: %s", renderedCmd)
|
||||
if err := tr.executeCommand(renderedCmd); err != nil {
|
||||
return fmt.Errorf("first execution failed: %w", err)
|
||||
}
|
||||
|
||||
// Execute the command twice if specified (for testing clone then pull)
|
||||
if scenario.RunTwice {
|
||||
log.Printf("Executing (second time): %s", renderedCmd)
|
||||
if err := tr.executeCommand(renderedCmd); err != nil {
|
||||
return fmt.Errorf("second execution failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the expected structure
|
||||
if err := tr.verifyExpectedStructure(scenario.ExpectedStructure); err != nil {
|
||||
return fmt.Errorf("structure verification failed: %w", err)
|
||||
}
|
||||
|
||||
// Verify no tokens in git remotes by default (unless explicitly skipped)
|
||||
if len(scenario.ExpectedStructure) > 0 && !scenario.SkipTokenVerification {
|
||||
if err := tr.verifyNoTokensInRemotes(scenario.ExpectedStructure, tr.context.Token); err != nil {
|
||||
return fmt.Errorf("token verification failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Execute verification commands if any
|
||||
for _, verifyCmd := range scenario.VerifyCommands {
|
||||
renderedCmd, err := tr.renderTemplate(verifyCmd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to render verify command: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Verify: %s", renderedCmd)
|
||||
if err := tr.executeCommand(renderedCmd); err != nil {
|
||||
return fmt.Errorf("verification command failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) renderTemplate(tmplText string) (string, error) {
|
||||
tmpl, err := template.New("command").Parse(tmplText)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
if err := tmpl.Execute(&buf, tr.context); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) executeCommand(command string) error {
|
||||
parts := strings.Fields(command)
|
||||
if len(parts) == 0 {
|
||||
return fmt.Errorf("empty command")
|
||||
}
|
||||
|
||||
cmd := exec.Command(parts[0], parts[1:]...)
|
||||
cmd.Dir = tr.context.GhorgDir
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("command failed: %s\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) verifyExpectedStructure(expectedPaths []string) error {
|
||||
log.Printf("Verifying expected structure (%d paths)...", len(expectedPaths))
|
||||
|
||||
for _, expectedPath := range expectedPaths {
|
||||
fullPath := filepath.Join(tr.context.GhorgDir, expectedPath)
|
||||
|
||||
if _, err := os.Stat(fullPath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("expected path does not exist: %s", expectedPath)
|
||||
}
|
||||
return fmt.Errorf("failed to check path %s: %w", expectedPath, err)
|
||||
}
|
||||
|
||||
log.Printf("✓ Found: %s", expectedPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) verifyNoTokensInRemotes(expectedPaths []string, token string) error {
|
||||
for _, expectedPath := range expectedPaths {
|
||||
fullPath := filepath.Join(tr.context.GhorgDir, expectedPath)
|
||||
|
||||
// Check if this is a git repository directory
|
||||
if _, err := os.Stat(filepath.Join(fullPath, ".git")); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// Not a git repository, skip
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("failed to check .git directory in %s: %w", expectedPath, err)
|
||||
}
|
||||
|
||||
// Run git remote -v to get all remotes
|
||||
cmd := exec.Command("git", "remote", "-v")
|
||||
cmd.Dir = fullPath
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get git remotes for %s: %w\nOutput: %s", expectedPath, err, string(output))
|
||||
}
|
||||
|
||||
// Check if the token appears in any remote URL
|
||||
remoteOutput := string(output)
|
||||
if strings.Contains(remoteOutput, token) {
|
||||
return fmt.Errorf("token found in git remote URLs for %s:\n%s", expectedPath, remoteOutput)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) ensureGhorgDirectoryExists() error {
|
||||
log.Printf("Ensuring ghorg directory exists: %s", tr.context.GhorgDir)
|
||||
|
||||
// Check if directory already exists
|
||||
if _, err := os.Stat(tr.context.GhorgDir); err == nil {
|
||||
log.Printf("Ghorg directory already exists: %s", tr.context.GhorgDir)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create the directory with appropriate permissions
|
||||
if err := os.MkdirAll(tr.context.GhorgDir, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create directory %s: %w", tr.context.GhorgDir, err)
|
||||
}
|
||||
|
||||
log.Printf("Created ghorg directory: %s", tr.context.GhorgDir)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) cleanupTestDirectories() error {
|
||||
log.Println("Cleaning up test directories...")
|
||||
|
||||
// Delete all folders that start with local-gitea-* in the ghorg directory
|
||||
matches, err := filepath.Glob(filepath.Join(tr.context.GhorgDir, "local-gitea-*"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, match := range matches {
|
||||
if err := os.RemoveAll(match); err != nil {
|
||||
log.Printf("Warning: Failed to remove %s: %v", match, err)
|
||||
} else {
|
||||
log.Printf("Removed: %s", match)
|
||||
}
|
||||
}
|
||||
|
||||
// Also clean up gitea.example.com directory if it exists
|
||||
giteaDir := filepath.Join(tr.context.GhorgDir, "gitea.example.com:3000")
|
||||
if _, err := os.Stat(giteaDir); err == nil {
|
||||
if err := os.RemoveAll(giteaDir); err != nil {
|
||||
log.Printf("Warning: Failed to remove %s: %v", giteaDir, err)
|
||||
} else {
|
||||
log.Printf("Removed: %s", giteaDir)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tr *TestRunner) RunSpecificTest(testName string) error {
|
||||
// Ensure the ghorg directory exists
|
||||
if err := tr.ensureGhorgDirectoryExists(); err != nil {
|
||||
return fmt.Errorf("failed to create ghorg directory: %w", err)
|
||||
}
|
||||
|
||||
for _, scenario := range tr.config.TestScenarios {
|
||||
if scenario.Name == testName {
|
||||
if scenario.Disabled {
|
||||
return fmt.Errorf("test '%s' is disabled and cannot be run", testName)
|
||||
}
|
||||
log.Printf("Running specific test: %s", testName)
|
||||
return tr.runTest(&scenario)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("test not found: %s", testName)
|
||||
}
|
||||
|
||||
func (tr *TestRunner) ListTests() {
|
||||
log.Printf("Available tests:")
|
||||
for i, scenario := range tr.config.TestScenarios {
|
||||
status := ""
|
||||
if scenario.Disabled {
|
||||
status = " (DISABLED)"
|
||||
}
|
||||
log.Printf("%d. %s - %s%s", i+1, scenario.Name, scenario.Description, status)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
configPath = flag.String("config", "configs/test-scenarios.json", "Path to test scenarios configuration file")
|
||||
baseURL = flag.String("base-url", "http://gitea.example.com:3000", "Gitea base URL")
|
||||
token = flag.String("token", "", "Gitea API token")
|
||||
ghorgDir = flag.String("ghorg-dir", "", "Ghorg directory (default: $HOME/ghorg)")
|
||||
testName = flag.String("test", "", "Run specific test by name")
|
||||
listTests = flag.Bool("list", false, "List available tests")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
if *token == "" {
|
||||
log.Fatal("Token is required")
|
||||
}
|
||||
|
||||
if *ghorgDir == "" {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get home directory: %v", err)
|
||||
}
|
||||
*ghorgDir = filepath.Join(homeDir, "ghorg")
|
||||
}
|
||||
|
||||
context := &TestContext{
|
||||
BaseURL: *baseURL,
|
||||
Token: *token,
|
||||
GhorgDir: *ghorgDir,
|
||||
}
|
||||
|
||||
runner, err := NewTestRunner(*configPath, context)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create test runner: %v", err)
|
||||
}
|
||||
|
||||
if *listTests {
|
||||
runner.ListTests()
|
||||
return
|
||||
}
|
||||
|
||||
if *testName != "" {
|
||||
if err := runner.RunSpecificTest(*testName); err != nil {
|
||||
log.Fatalf("Test failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := runner.RunAllTests(); err != nil {
|
||||
log.Fatalf("Integration tests failed: %v", err)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user