[IMP] manual deployment workflow with dry-run and filters
Replace automatic deployment (on push) with manual workflow_dispatch: - Version filter: deploy to all versions or specific one (16.0, 18.0) - Repo filter: deploy to all repos or comma-separated list - Dry-run mode: preview changes without creating PRs - Detailed summary with emoji indicators and statistics Benefits: - Full control over deployment scope and timing - Safe preview before creating 50+ PRs - Targeted deployments for testing Update README with new deployment guide and examples.
This commit is contained in:
@@ -1,16 +1,45 @@
|
||||
name: Sync Config to All Odoo Repositories
|
||||
run-name: ${{ gitea.actor }} is deploying new pre-commit config 🚀
|
||||
name: Deploy CI Config
|
||||
run-name: "${{ gitea.actor }} deploying config [${{ inputs.version }}] to [${{ inputs.repos || 'all repos' }}]${{ inputs.dry_run && ' (DRY-RUN)' || '' }}"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Odoo version to deploy'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- all
|
||||
- '16.0'
|
||||
- '18.0'
|
||||
default: 'all'
|
||||
repos:
|
||||
description: 'Target repos (comma-separated, empty = all *-addons/*-tools)'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
dry_run:
|
||||
description: 'Dry run (preview changes without creating PRs)'
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Show deployment parameters
|
||||
run: |
|
||||
echo "============================================"
|
||||
echo " DEPLOYMENT PARAMETERS"
|
||||
echo "============================================"
|
||||
echo "Version: ${{ inputs.version }}"
|
||||
echo "Repos: ${{ inputs.repos || '(all)' }}"
|
||||
echo "Dry-run: ${{ inputs.dry_run }}"
|
||||
echo "============================================"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
@@ -24,112 +53,182 @@ jobs:
|
||||
run: |
|
||||
git clone --single-branch --branch main "${GITEA_SERVER}/${ORG_NAME}/${CONFIG_REPO}.git" config-repo
|
||||
|
||||
- name: Detect available Odoo versions
|
||||
id: versions
|
||||
- name: Determine versions to deploy
|
||||
run: |
|
||||
# List directories in config/ that are not "common" (these are version directories)
|
||||
VERSIONS=$(ls -d config-repo/config/*/ | xargs -n1 basename | grep -v common | tr '\n' ' ')
|
||||
echo "Available versions: $VERSIONS"
|
||||
# List all available versions
|
||||
ALL_VERSIONS=$(ls -d config-repo/config/*/ | xargs -n1 basename | grep -v common | tr '\n' ' ')
|
||||
echo "Available versions: $ALL_VERSIONS"
|
||||
|
||||
# Filter based on input
|
||||
if [ "${{ inputs.version }}" = "all" ]; then
|
||||
VERSIONS="$ALL_VERSIONS"
|
||||
else
|
||||
VERSIONS="${{ inputs.version }}"
|
||||
fi
|
||||
|
||||
echo "Versions to deploy: $VERSIONS"
|
||||
echo "VERSIONS=$VERSIONS" >> $GITEA_ENV
|
||||
|
||||
- name: Get list of all repos in organization
|
||||
- name: Build target repos list
|
||||
env:
|
||||
GITEA_SERVER: "https://git.elabore.coop"
|
||||
ORG_NAME: "Elabore"
|
||||
GITEA_TOKEN: ${{ secrets.ELABORE_BOT_TOKEN }}
|
||||
INPUT_REPOS: ${{ inputs.repos }}
|
||||
run: |
|
||||
page=1
|
||||
per_page=50
|
||||
REPO_LIST="repos.txt"
|
||||
> $REPO_LIST
|
||||
while true; do
|
||||
echo "Fetching page $page"
|
||||
response=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_SERVER}/api/v1/orgs/${ORG_NAME}/repos?page=${page}&limit=${per_page}")
|
||||
count=$(echo "$response" | jq 'length')
|
||||
if [ "$count" -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
echo "$response" | jq -r '.[].name' >> $REPO_LIST
|
||||
page=$((page + 1))
|
||||
done
|
||||
echo "Repositories found:"
|
||||
cat $REPO_LIST
|
||||
|
||||
- name: Sync config to each repo
|
||||
if [ -n "$INPUT_REPOS" ]; then
|
||||
# User specified repos - use them directly
|
||||
echo "Using user-specified repos: $INPUT_REPOS"
|
||||
echo "$INPUT_REPOS" | tr ',' '\n' | sed 's/^ *//;s/ *$//' > $REPO_LIST
|
||||
else
|
||||
# Fetch all repos from organization
|
||||
page=1
|
||||
per_page=50
|
||||
while true; do
|
||||
echo "Fetching page $page"
|
||||
response=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_SERVER}/api/v1/orgs/${ORG_NAME}/repos?page=${page}&limit=${per_page}")
|
||||
count=$(echo "$response" | jq 'length')
|
||||
if [ "$count" -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
# Filter for *-addons and *-tools repos only
|
||||
echo "$response" | jq -r '.[].name | select(endswith("-addons") or endswith("-tools"))' >> $REPO_LIST
|
||||
page=$((page + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Target repositories:"
|
||||
cat $REPO_LIST
|
||||
echo ""
|
||||
echo "Total: $(wc -l < $REPO_LIST) repos"
|
||||
|
||||
- name: Deploy config to repos
|
||||
env:
|
||||
GITEA_SERVER: "git.elabore.coop"
|
||||
ORG_NAME: "Elabore"
|
||||
CONFIG_REPO: "odoo-elabore-ci"
|
||||
GITEA_TOKEN: ${{ secrets.ELABORE_BOT_TOKEN }}
|
||||
VERSIONS: ${{ env.VERSIONS }}
|
||||
DRY_RUN: ${{ inputs.dry_run }}
|
||||
run: |
|
||||
REPO_LIST="repos.txt"
|
||||
SUMMARY_FILE="deployment_summary.txt"
|
||||
> $SUMMARY_FILE
|
||||
|
||||
pr_created=0
|
||||
pr_skipped_no_changes=0
|
||||
pr_skipped_no_branch=0
|
||||
errors=0
|
||||
|
||||
while read repo; do
|
||||
# Skip empty lines
|
||||
[ -z "$repo" ] && continue
|
||||
|
||||
# Skip the config repo itself
|
||||
if [ "$repo" = "$CONFIG_REPO" ]; then
|
||||
echo "Skipping config repo: $repo"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Skip repos not matching suffixes -addons and -tools
|
||||
if ! [[ "$repo" == *-addons ]] && ! [[ "$repo" == *-tools ]]; then
|
||||
echo "Skipping $repo (does not end with -addons or -tools)"
|
||||
echo "⏭️ Skipping config repo: $repo"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Processing repo: $repo"
|
||||
echo "📦 Processing: $repo"
|
||||
echo "=========================================="
|
||||
|
||||
# Try each Odoo version
|
||||
for VERSION in $VERSIONS; do
|
||||
echo "--- Trying version $VERSION for $repo ---"
|
||||
echo ""
|
||||
echo "--- Version $VERSION ---"
|
||||
|
||||
# Try to clone the target repo at this version branch
|
||||
if ! git clone --quiet --single-branch --branch "$VERSION" "https://elabore_bot:${GITEA_TOKEN}@${GITEA_SERVER}/${ORG_NAME}/${repo}.git" "target-${repo}-${VERSION}" 2>/dev/null; then
|
||||
echo "Branch $VERSION does not exist in $repo, skipping"
|
||||
echo "⚠️ Branch $VERSION does not exist in $repo"
|
||||
pr_skipped_no_branch=$((pr_skipped_no_branch + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
cd "target-${repo}-${VERSION}" || { echo "Failed to enter target-${repo}-${VERSION}"; exit 1; }
|
||||
cd "target-${repo}-${VERSION}" || { echo "❌ Failed to enter directory"; errors=$((errors + 1)); continue; }
|
||||
|
||||
# Copy common files first
|
||||
echo "Copying common config files..."
|
||||
rsync -av ../config-repo/config/common/ .
|
||||
rsync -a ../config-repo/config/common/ .
|
||||
|
||||
# Copy version-specific files (overwrites common if conflict)
|
||||
echo "Copying $VERSION-specific config files..."
|
||||
rsync -av ../config-repo/config/${VERSION}/ .
|
||||
rsync -a ../config-repo/config/${VERSION}/ .
|
||||
|
||||
git add -N .
|
||||
|
||||
# If there are no changes, skip
|
||||
# Check for changes
|
||||
if git diff --quiet; then
|
||||
echo "No changes for $repo on branch $VERSION"
|
||||
echo "✅ No changes needed for $repo:$VERSION"
|
||||
pr_skipped_no_changes=$((pr_skipped_no_changes + 1))
|
||||
else
|
||||
echo "Changes detected for $repo:$VERSION – committing & pushing"
|
||||
git config user.name "elabore_bot"
|
||||
git config user.email "gitea.bot@elabore.coop"
|
||||
git checkout -b "${VERSION}-config_deployment"
|
||||
git add .
|
||||
git commit -m "Sync config from ${CONFIG_REPO} (version ${VERSION})"
|
||||
echo "📝 Changes detected for $repo:$VERSION"
|
||||
echo ""
|
||||
echo "Changed files:"
|
||||
git diff --stat
|
||||
echo ""
|
||||
|
||||
echo "Pushing to $repo on branch $VERSION"
|
||||
git push --quiet origin "${VERSION}-config_deployment":refs/for/"${VERSION}" \
|
||||
-o topic="${VERSION}-config_deployment" \
|
||||
-o title="Sync config from ${CONFIG_REPO} (version ${VERSION})" \
|
||||
-o force-push || { echo "Push failed for $repo:$VERSION"; exit 1; }
|
||||
echo "Push done for $repo:$VERSION"
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "🔍 DRY-RUN: Would create PR for $repo:$VERSION"
|
||||
echo "[DRY-RUN] $repo:$VERSION - PR would be created" >> ../$SUMMARY_FILE
|
||||
else
|
||||
echo "🚀 Creating PR for $repo:$VERSION"
|
||||
git config user.name "elabore_bot"
|
||||
git config user.email "gitea.bot@elabore.coop"
|
||||
git checkout -b "${VERSION}-config_deployment"
|
||||
git add .
|
||||
git commit -m "Sync config from ${CONFIG_REPO} (version ${VERSION})"
|
||||
|
||||
if git push --quiet origin "${VERSION}-config_deployment":refs/for/"${VERSION}" \
|
||||
-o topic="${VERSION}-config_deployment" \
|
||||
-o title="Sync config from ${CONFIG_REPO} (version ${VERSION})" \
|
||||
-o force-push; then
|
||||
echo "✅ PR created for $repo:$VERSION"
|
||||
echo "[CREATED] $repo:$VERSION - PR created" >> ../$SUMMARY_FILE
|
||||
pr_created=$((pr_created + 1))
|
||||
else
|
||||
echo "❌ Push failed for $repo:$VERSION"
|
||||
echo "[ERROR] $repo:$VERSION - Push failed" >> ../$SUMMARY_FILE
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
cd ..
|
||||
rm -rf "target-${repo}-${VERSION}"
|
||||
echo "Cleanup done for $repo:$VERSION"
|
||||
|
||||
done
|
||||
|
||||
echo "Moving to next repo"
|
||||
echo ""
|
||||
|
||||
done < $REPO_LIST
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " DEPLOYMENT SUMMARY"
|
||||
echo "============================================"
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Mode: DRY-RUN (no PRs created)"
|
||||
else
|
||||
echo "Mode: LIVE"
|
||||
fi
|
||||
echo ""
|
||||
echo "PRs created: $pr_created"
|
||||
echo "Skipped (no changes): $pr_skipped_no_changes"
|
||||
echo "Skipped (branch missing): $pr_skipped_no_branch"
|
||||
echo "Errors: $errors"
|
||||
echo ""
|
||||
|
||||
if [ -s $SUMMARY_FILE ]; then
|
||||
echo "Details:"
|
||||
cat $SUMMARY_FILE
|
||||
fi
|
||||
|
||||
echo "============================================"
|
||||
|
||||
# Exit with error if there were failures
|
||||
if [ $errors -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
67
README.md
67
README.md
@@ -17,7 +17,7 @@ This repository manages linting and CI configuration centrally for all Odoo repo
|
||||
```
|
||||
odoo-elabore-ci/
|
||||
├── .gitea/workflows/
|
||||
│ └── deploy-config.yml # Automatic deployment workflow
|
||||
│ └── deploy-config.yml # Manual deployment workflow (with dry-run)
|
||||
└── config/
|
||||
├── common/ # Shared files (all versions)
|
||||
│ ├── .editorconfig
|
||||
@@ -43,14 +43,21 @@ odoo-elabore-ci/
|
||||
|
||||
### Deployment Workflow (`deploy-config.yml`)
|
||||
|
||||
When a push is made to the `main` branch of this repository:
|
||||
The deployment is **manually triggered** via Gitea Actions interface, giving you full control over what gets deployed and where.
|
||||
|
||||
1. The workflow automatically detects available versions (folders in `config/` other than `common/`)
|
||||
2. For each `*-addons` or `*-tools` repository in the organization:
|
||||
- For each configured Odoo version (16.0, 18.0, etc.):
|
||||
- Attempts to clone the corresponding branch from the target repo
|
||||
- If it exists: copies `config/common/` then `config/{version}/`
|
||||
- Creates a Pull Request if changes are detected
|
||||
**Features:**
|
||||
- **Version filter**: Deploy to all versions or a specific one (16.0, 18.0)
|
||||
- **Repo filter**: Deploy to all repos or specific ones (comma-separated)
|
||||
- **Dry-run mode**: Preview changes without creating any PRs
|
||||
|
||||
**Process:**
|
||||
1. Detects available versions (folders in `config/` other than `common/`)
|
||||
2. For each target repository:
|
||||
- For each selected Odoo version:
|
||||
- Attempts to clone the corresponding branch
|
||||
- Copies `config/common/` then `config/{version}/`
|
||||
- In dry-run: shows what would change
|
||||
- In live mode: creates a Pull Request if changes detected
|
||||
|
||||
### CI Workflow (`pre-commit.yml`)
|
||||
|
||||
@@ -73,6 +80,44 @@ Deployed to each target repository, this workflow runs on every Pull Request:
|
||||
|
||||
## Usage Guide
|
||||
|
||||
### Deploying Configuration
|
||||
|
||||
Deployment is done via the Gitea Actions interface:
|
||||
|
||||
1. Go to **Gitea** → `odoo-elabore-ci` → **Actions**
|
||||
2. Select **"Deploy CI Config"** workflow
|
||||
3. Click **"Run workflow"**
|
||||
4. Fill in the parameters:
|
||||
|
||||
| Parameter | Description | Examples |
|
||||
|-----------|-------------|----------|
|
||||
| **Version** | Odoo version to deploy | `all`, `16.0`, `18.0` |
|
||||
| **Repos** | Target repos (empty = all) | `crm-addons, hr-addons` |
|
||||
| **Dry-run** | Preview without creating PRs | `true` (recommended first) |
|
||||
|
||||
#### Deployment Examples
|
||||
|
||||
| I want to... | Version | Repos | Dry-run |
|
||||
|--------------|---------|-------|---------|
|
||||
| Preview all changes | `all` | *(empty)* | ✅ |
|
||||
| Deploy 16.0 to one repo | `16.0` | `crm-addons` | ❌ |
|
||||
| Deploy 18.0 to multiple repos | `18.0` | `crm-addons, hr-addons` | ❌ |
|
||||
| Deploy all versions everywhere | `all` | *(empty)* | ❌ |
|
||||
|
||||
#### Recommended Workflow
|
||||
|
||||
```
|
||||
1. Make changes in config/
|
||||
2. git commit && git push origin main
|
||||
→ Nothing happens (no auto-deploy)
|
||||
|
||||
3. Run workflow with DRY-RUN enabled
|
||||
→ Review the logs to see what would change
|
||||
|
||||
4. If satisfied, run again WITHOUT dry-run
|
||||
→ PRs are created in target repos
|
||||
```
|
||||
|
||||
### Modifying CI Configuration
|
||||
|
||||
1. **Edit files in `config/`**:
|
||||
@@ -86,7 +131,7 @@ Deployed to each target repository, this workflow runs on every Pull Request:
|
||||
git push origin main
|
||||
```
|
||||
|
||||
3. **The workflow automatically creates PRs** in all affected repos
|
||||
3. **Trigger deployment manually** (see above)
|
||||
|
||||
### Adding a New Odoo Version
|
||||
|
||||
@@ -117,7 +162,9 @@ Deployed to each target repository, this workflow runs on every Pull Request:
|
||||
git push origin main
|
||||
```
|
||||
|
||||
The workflow will automatically detect the new folder and deploy the configuration to repos with a `19.0` branch.
|
||||
5. **Deploy** via Gitea Actions:
|
||||
- The new version will appear in the "Version" dropdown
|
||||
- Use dry-run first to verify which repos have a `19.0` branch
|
||||
|
||||
## Secrets Configuration
|
||||
|
||||
|
||||
Reference in New Issue
Block a user