Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01c9563d1d | ||
| c7a7d8cd67 | |||
| d3bf936570 |
@@ -151,11 +151,55 @@ jobs:
|
||||
TEST_PGSQL_SCHEMA: gtestschema
|
||||
GITEA_I_AM_BEING_UNSAFE_RUNNING_AS_ROOT: true
|
||||
|
||||
# Create release job - runs first to create the release before build jobs upload
|
||||
create-release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
outputs:
|
||||
release_id: ${{ steps.create.outputs.release_id }}
|
||||
steps:
|
||||
- name: Create or get release
|
||||
id: create
|
||||
run: |
|
||||
TAG="${{ github.ref_name }}"
|
||||
echo "Creating/getting release for tag: $TAG"
|
||||
|
||||
# Try to get existing release first
|
||||
EXISTING=$(curl -sf \
|
||||
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
|
||||
"https://direct.git.marketally.com/api/v1/repos/${{ github.repository }}/releases/tags/$TAG" 2>/dev/null || echo "")
|
||||
|
||||
if echo "$EXISTING" | grep -q '"id":[0-9]'; then
|
||||
RELEASE_ID=$(echo "$EXISTING" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
|
||||
echo "Found existing release: $RELEASE_ID"
|
||||
echo "release_id=$RELEASE_ID" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create new release
|
||||
echo "Creating new release..."
|
||||
RESPONSE=$(curl -sf -X POST \
|
||||
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"tag_name":"'"$TAG"'","name":"Gitea '"$TAG"'","body":"Official release of Gitea '"$TAG"'.","draft":false,"prerelease":false}' \
|
||||
"https://direct.git.marketally.com/api/v1/repos/${{ github.repository }}/releases" 2>&1)
|
||||
|
||||
if echo "$RESPONSE" | grep -q '"id":[0-9]'; then
|
||||
RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
|
||||
echo "Created release: $RELEASE_ID"
|
||||
echo "release_id=$RELEASE_ID" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "ERROR: Failed to create release: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build job for binaries
|
||||
build:
|
||||
name: Build Binaries
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint]
|
||||
needs: [lint, create-release]
|
||||
if: always() && needs.lint.result == 'success' && (needs.create-release.result == 'success' || needs.create-release.result == 'skipped')
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -223,62 +267,42 @@ jobs:
|
||||
|
||||
- name: Upload to release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
|
||||
run: |
|
||||
set -e
|
||||
VERSION=$(git describe --tags --always 2>/dev/null || echo "dev")
|
||||
echo "Uploading binaries for $VERSION"
|
||||
|
||||
# Get or create release (with retry for race conditions)
|
||||
TAG="${{ github.ref_name }}"
|
||||
for i in 1 2 3; do
|
||||
EXISTING=$(curl -sf \
|
||||
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
|
||||
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/tags/$TAG" 2>/dev/null || echo "")
|
||||
|
||||
if echo "$EXISTING" | grep -q '"id":[0-9]'; then
|
||||
RELEASE_ID=$(echo "$EXISTING" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
|
||||
echo "Found existing release: $RELEASE_ID"
|
||||
break
|
||||
else
|
||||
echo "Attempt $i: Creating release..."
|
||||
RESPONSE=$(curl -sf -X POST \
|
||||
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"tag_name":"'"$TAG"'","name":"GitCaddy '"$TAG"'","body":"Official release.","draft":false,"prerelease":false}' \
|
||||
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases" 2>&1 || echo "")
|
||||
|
||||
if echo "$RESPONSE" | grep -q '"id":[0-9]'; then
|
||||
RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
|
||||
echo "Created release: $RELEASE_ID"
|
||||
break
|
||||
fi
|
||||
echo "Failed to create, retrying in 5s..."
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
echo "Uploading binaries to release ID: $RELEASE_ID"
|
||||
|
||||
if [ -z "$RELEASE_ID" ]; then
|
||||
echo "ERROR: Could not get or create release"
|
||||
echo "ERROR: No release ID provided"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Upload files
|
||||
# Upload files with retry
|
||||
for file in dist/*; do
|
||||
if [ -f "$file" ]; then
|
||||
filename=$(basename "$file")
|
||||
echo "Uploading $filename..."
|
||||
|
||||
UPLOAD_RESPONSE=$(curl -sf -X POST \
|
||||
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
|
||||
-F "attachment=@$file" \
|
||||
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=$filename" 2>&1)
|
||||
for attempt in 1 2 3; do
|
||||
UPLOAD_RESPONSE=$(curl -sf -X POST \
|
||||
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
|
||||
-F "attachment=@$file" \
|
||||
"https://direct.git.marketally.com/api/v1/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=$filename" 2>&1 || echo "")
|
||||
|
||||
if echo "$UPLOAD_RESPONSE" | grep -q '"id":[0-9]'; then
|
||||
echo "✓ Uploaded $filename successfully"
|
||||
else
|
||||
echo "✗ Failed to upload $filename: $UPLOAD_RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
if echo "$UPLOAD_RESPONSE" | grep -q '"id":[0-9]'; then
|
||||
echo "✓ Uploaded $filename successfully"
|
||||
break
|
||||
else
|
||||
if [ $attempt -lt 3 ]; then
|
||||
echo "Attempt $attempt failed, retrying in 5s..."
|
||||
sleep 5
|
||||
else
|
||||
echo "✗ Failed to upload $filename after 3 attempts: $UPLOAD_RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
echo "All uploads complete!"
|
||||
|
||||
@@ -14,12 +14,10 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAzureBlobStorageIterator(t *testing.T) {
|
||||
if os.Getenv("CI") == "" {
|
||||
t.Skip("azureBlobStorage not present outside of CI")
|
||||
return
|
||||
}
|
||||
testStorageIterator(t, setting.AzureBlobStorageType, &setting.Storage{
|
||||
// azureBlobTestConfig returns the Azure Blob storage config for tests.
|
||||
// Returns nil if Azurite is not available (skip the test).
|
||||
func azureBlobTestConfig() *setting.Storage {
|
||||
return &setting.Storage{
|
||||
AzureBlobConfig: setting.AzureBlobStorageConfig{
|
||||
// https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio-code#ip-style-url
|
||||
Endpoint: "http://devstoreaccount1.azurite.local:10000",
|
||||
@@ -28,7 +26,36 @@ func TestAzureBlobStorageIterator(t *testing.T) {
|
||||
AccountKey: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==",
|
||||
Container: "test",
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// skipIfNoAzurite skips the test if Azurite service is not available.
|
||||
// In CI, we always skip since Azurite is not available in our runner environment.
|
||||
func skipIfNoAzurite(t *testing.T) {
|
||||
t.Helper()
|
||||
if os.Getenv("CI") != "" {
|
||||
t.Skip("azureBlobStorage requires Azurite service which is not available in CI")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAzureBlobStorageIterator(t *testing.T) {
|
||||
skipIfNoAzurite(t)
|
||||
|
||||
cfg := azureBlobTestConfig()
|
||||
// Try to create storage to verify Azurite is available
|
||||
s, err := NewStorage(setting.AzureBlobStorageType, cfg)
|
||||
if err != nil {
|
||||
t.Skipf("azureBlobStorage not available: %v", err)
|
||||
}
|
||||
// Clean up the test storage
|
||||
_ = s.Delete("a/1.txt")
|
||||
_ = s.Delete("ab/1.txt")
|
||||
_ = s.Delete("b/1.txt")
|
||||
_ = s.Delete("b/2.txt")
|
||||
_ = s.Delete("b/3.txt")
|
||||
_ = s.Delete("b/x 4.txt")
|
||||
|
||||
testStorageIterator(t, setting.AzureBlobStorageType, cfg)
|
||||
}
|
||||
|
||||
func TestAzureBlobStoragePath(t *testing.T) {
|
||||
@@ -58,22 +85,12 @@ func TestAzureBlobStoragePath(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_azureBlobObject(t *testing.T) {
|
||||
if os.Getenv("CI") == "" {
|
||||
t.Skip("azureBlobStorage not present outside of CI")
|
||||
return
|
||||
}
|
||||
skipIfNoAzurite(t)
|
||||
|
||||
s, err := NewStorage(setting.AzureBlobStorageType, &setting.Storage{
|
||||
AzureBlobConfig: setting.AzureBlobStorageConfig{
|
||||
// https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio-code#ip-style-url
|
||||
Endpoint: "http://devstoreaccount1.azurite.local:10000",
|
||||
// https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio-code#well-known-storage-account-and-key
|
||||
AccountName: "devstoreaccount1",
|
||||
AccountKey: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==",
|
||||
Container: "test",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
s, err := NewStorage(setting.AzureBlobStorageType, azureBlobTestConfig())
|
||||
if err != nil {
|
||||
t.Skipf("azureBlobStorage not available: %v", err)
|
||||
}
|
||||
|
||||
data := "Q2xTckt6Y1hDOWh0"
|
||||
_, err = s.Save("test.txt", strings.NewReader(data), int64(len(data)))
|
||||
|
||||
@@ -16,12 +16,9 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMinioStorageIterator(t *testing.T) {
|
||||
if os.Getenv("CI") == "" {
|
||||
t.Skip("minioStorage not present outside of CI")
|
||||
return
|
||||
}
|
||||
testStorageIterator(t, setting.MinioStorageType, &setting.Storage{
|
||||
// minioTestConfig returns the Minio storage config for tests.
|
||||
func minioTestConfig() *setting.Storage {
|
||||
return &setting.Storage{
|
||||
MinioConfig: setting.MinioStorageConfig{
|
||||
Endpoint: "minio:9000",
|
||||
AccessKeyID: "123456",
|
||||
@@ -29,7 +26,36 @@ func TestMinioStorageIterator(t *testing.T) {
|
||||
Bucket: "gitea",
|
||||
Location: "us-east-1",
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// skipIfNoMinio skips the test if Minio service is not available.
|
||||
// In CI, we always skip since Minio is not available in our runner environment.
|
||||
func skipIfNoMinio(t *testing.T) {
|
||||
t.Helper()
|
||||
if os.Getenv("CI") != "" {
|
||||
t.Skip("minioStorage requires Minio service which is not available in CI")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinioStorageIterator(t *testing.T) {
|
||||
skipIfNoMinio(t)
|
||||
|
||||
cfg := minioTestConfig()
|
||||
// Try to create storage to verify Minio is available
|
||||
s, err := NewStorage(setting.MinioStorageType, cfg)
|
||||
if err != nil {
|
||||
t.Skipf("minioStorage not available: %v", err)
|
||||
}
|
||||
// Clean up any existing test files
|
||||
_ = s.Delete("a/1.txt")
|
||||
_ = s.Delete("ab/1.txt")
|
||||
_ = s.Delete("b/1.txt")
|
||||
_ = s.Delete("b/2.txt")
|
||||
_ = s.Delete("b/3.txt")
|
||||
_ = s.Delete("b/x 4.txt")
|
||||
|
||||
testStorageIterator(t, setting.MinioStorageType, cfg)
|
||||
}
|
||||
|
||||
func TestMinioStoragePath(t *testing.T) {
|
||||
@@ -67,10 +93,8 @@ func TestMinioStoragePath(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestS3StorageBadRequest(t *testing.T) {
|
||||
if os.Getenv("CI") == "" {
|
||||
t.Skip("S3Storage not present outside of CI")
|
||||
return
|
||||
}
|
||||
skipIfNoMinio(t)
|
||||
|
||||
cfg := &setting.Storage{
|
||||
MinioConfig: setting.MinioStorageConfig{
|
||||
Endpoint: "minio:9000",
|
||||
|
||||
@@ -2937,6 +2937,7 @@
|
||||
"admin.dashboard.cleanup_hook_task_table": "Clean up hook_task table",
|
||||
"admin.dashboard.cleanup_packages": "Clean up expired packages",
|
||||
"admin.dashboard.cleanup_actions": "Clean up expired actions' resources",
|
||||
"admin.dashboard.cleanup_expired_upload_sessions": "Clean up expired upload sessions",
|
||||
"admin.dashboard.server_uptime": "Server Uptime",
|
||||
"admin.dashboard.current_goroutine": "Current Goroutines",
|
||||
"admin.dashboard.current_memory_usage": "Current Memory Usage",
|
||||
|
||||
Reference in New Issue
Block a user