⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/stale-template.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Stale Bot Action for Icinga
name: 'stale'

permissions:
issues: write

on:
schedule:
- cron: 0 13 * * 1-5

jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
close-issue-message: 'This issue has been automatically closed due to age/inactivity. If still relevant with current software version, feel free to create a new issue with updated details. '
stale-issue-label: 'stale'
exempt-issue-labels: 'ref/IP, ref/NP'
exempt-all-issue-milestones: true
days-before-issue-stale: 1780
days-before-issue-close: 0
operations-per-run: 15
enable-statistics: true
ignore-issue-updates: true
ascending: true
debug-only: true
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Icinga GitHub Actions

This repository contains workflow files for centralized management and scripts for distribution of GitHub Actions to all relevant Icinga repositories.

### Management Scripts
The two scripts can be used to distribute GitHub Actions workflow files to multiple repositories.
It works with a local repository set up and creates automatically PRs.

### Prerequisites
- GitHub CLI (`gh`) installed and authenticated
- Write permissions for target repositories

### Setup
```bash
# Create local repository
mkdir github-actions-deploy
cd github-actions-deploy
git init
git checkout -b main

# Set up workflow structure
git checkout -b <Branch>
mkdir -p .github/workflows
cp /path/to/action-file.yml .github/workflows/action-file.yml

# Create commit
git add -A
git commit -m "Commit Message"
```

### Execution
```bash
# All Icinga repositories
./list-repos.sh -p "Icinga/*" | ./sync.sh

# Specific repository patterns
./list-repos.sh -p "Icinga/icingaweb*" | ./sync.sh

# Dry-run
./list-repos.sh -p "Icinga/*" | ./sync.sh --dry-run

#show help
./sync.sh -h
```
107 changes: 107 additions & 0 deletions list-repos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/bash

# Creates a list of repositories based on patterns and filters all public, non-archived repositories

PATTERNS=()

RED='\033[0;31m'
NC='\033[0m' # No Color (Reset)

show_help() {
cat << EOF
GitHub Repository List Generator

Usage: $0 [OPTIONS]

OPTIONS:
-p, --pattern PATTERN Repository pattern (required)
Examples: "Icinga/icingaweb*", "MyOrg/*", "Icinga/icinga2"
-h, --help Show this help

EXAMPLES:
# All public Icinga repos
$0 -p "Icinga/*"

# Only icingaweb repos in Icinga organization
$0 -p "Icinga/icingaweb*"

EOF
}

# Parameter parsen
while [[ $# -gt 0 ]]; do
case $1 in
-p|--pattern)
PATTERNS+=("$2")
shift 2
;;
-h|--help)
show_help >&2
exit 0
;;
*)
echo "Unknown option: $1" >&2
show_help >&2
exit 1
;;
esac
done

# Check if patterns contain organization info
if [[ "${PATTERNS[0]}" != *"/"* ]]; then
echo -e "${RED}Error: Pattern must include organization (e.g., 'Icinga/icingaweb*')${NC}" >&2
show_help >&2
exit 1
fi

get_repositories() {
local org="${PATTERNS[0]%%/*}"

# List all public, non-archived repositories for the organization
gh repo list "$org" --limit 1000 --no-archived --visibility public --json name,owner | \
jq -r '.[] | "\(.owner.login)/\(.name)"'
}

matches_pattern() {
local repo="$1"
local pattern="$2"

# Bash pattern matching
case "$repo" in
$pattern) return 0 ;;
*) return 1 ;;
esac
}

# Pattern filtering
filter_repositories() {
local repos=()

while IFS= read -r repo; do
for pattern in "${PATTERNS[@]}"; do
if matches_pattern "$repo" "$pattern"; then
repos+=("$repo")
break
fi
done
done

printf '%s\n' "${repos[@]}"
}

main() {

# Get and filter repositories
mapfile -t repositories < <(get_repositories | filter_repositories)

if [[ ${#repositories[@]} -eq 0 ]]; then
echo -e "${RED}No repositories found matching the patterns${NC}" >&2
exit 1
fi

# Output repositories to stdout
printf '%s\n' "${repositories[@]}"
}

# Script execution
main
11 changes: 11 additions & 0 deletions stale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: stale action

on:
push:
branches:
- main

jobs:
stale:
uses: icinga/github-actions/.github/workflows/stale.yml@main
secrets: inherit
200 changes: 200 additions & 0 deletions sync.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#!/bin/bash

# GitHub Action Deployment:
# 1. Receives repository list from `list-repos.sh`
# 2. Creates temporary branches for each target repository
# 3. Cherry-picks local branch into target branch
# 4. Pushes changes and creates pull requests with auto-generated title and body from commits
# 5. Cleans up local environment (deletes branches/remotes)

# Configuration
DRY_RUN=false

# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color (Reset)

show_help() {
cat << EOF
GitHub Action Deployment - Push Branch to Multiple Repos

Usage: $0 [OPTIONS]

This script usees stdin to push the current branch to multiple repositories and creates PRs with automated message from commits.

OPTIONS:
--dry-run Only show what would be done, without changes
-h, --help Show this help

EXAMPLES:
# Use with pipe from list-repos.sh
./list-repos.sh -p "Icinga/*" | sync.sh

# Dry-run to see what would happen
./list-repos.sh -p "Icinga/*" | $0 --dry-run
EOF
}

# Parameter parsen
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
show_help >&2
exit 0
;;
*)
echo "Unknown option: $1" >&2
show_help >&2
exit 1
;;
esac
done

# Get current branch
BRANCH_TO_DISTRIBUTE=$(git branch --show-current)
if [[ -z "$BRANCH_TO_DISTRIBUTE" ]]; then
exit 1
fi

#global arrays
created_branches=()
updated_repositories=()
failed_repositories=()

deploy_to_repo() {
local repo="$1"

# Create remote name from repo (replace / with -)
local remote_name="${repo//\//-}"
WORKING_BRUNCH="$remote_name/$BRANCH_TO_DISTRIBUTE"

if [[ "$DRY_RUN" == "true" ]]; then
echo "[DRY-RUN] $repo - would cherry-pick branch '$BRANCH_TO_DISTRIBUTE' to $WORKING_BRUNCH" >&2
return 0
fi

echo -e "${BLUE}Processing $repo...${NC}" >&2

created_branches+=("$WORKING_BRUNCH")
remote_repos+=("$remote_name")
local expected_url="https://github.com/${repo}.git"

#get and add remote repository url
if ! git remote get-url "$remote_name"; then
git remote add "$remote_name" "$expected_url"
elif [[ "$(git remote get-url "$remote_name")" != "$expected_url" ]]; then
echo -e "${RED}Error: Remote $remote_name URL mismatch${NC}" >&2
return 1
fi

# Fetch the remote repository
if ! git fetch "$remote_name"; then
echo -e "${RED}$repo (fetch failed)${NC}" >&2
return 1
fi

# Create new branch from remote main
if ! git checkout -b "$WORKING_BRUNCH" "$remote_name/main"; then
echo -e "${RED}Can not create new branch $WORKING_BRUNCH${NC}" >&2
return 1
fi

#cherry-pick branch
if ! git cherry-pick "$BRANCH_TO_DISTRIBUTE"; then
echo -e "${RED}$repo (cherry-pick failed for branch $lworking_branch)${NC}" >&2
git cherry-pick --abort || true
return 1
fi

# Push to remote repository
if ! git push "$remote_name" "HEAD:$BRANCH_TO_DISTRIBUTE"; then
echo -e "${RED}$repo (push failed)${NC}" >&2
return 1
fi

# Create pull request
if gh pr create --repo "$repo" --fill --head "$BRANCH_TO_DISTRIBUTE" --base main; then
echo -e "${GREEN}$repo (PR created)${NC}" >&2
else
echo -e "${RED}$repo (PR creation failed)${NC}" >&2
return 1
fi

return 0
}

#set trap to clean up
cleanup() {
git checkout "$BRANCH_TO_DISTRIBUTE" || git checkout main

for branch in "${created_branches[@]}"; do
git branch -D "$branch"
done

for remote_repo in "${remote_repos[@]}"; do
git remote remove "$remote_repo"
done

}

print_results() {
echo >&2
echo "=== RESULTS ===" >&2

if [[ ${#updated_repositories[@]} -gt 0 ]]; then
for repo in "${updated_repositories[@]}"; do
echo -e "${GREEN}${repo} updated ${NC}"
done
fi

if [[ ${#failed_repositories[@]} -gt 0 ]]; then
for repo in "${failed_repositories[@]}"; do
echo -e "${RED}${repo} failed ${NC}"
done
fi
}

#trap to clean up
trap 'print_results; cleanup' EXIT INT TERM

main() {

# Read repository list from file or stdin
local repositories=()
mapfile -t repositories

# Remove empty lines from stdin
local filtered_repos=()
for repo in "${repositories[@]}"; do
[[ -n "$repo" ]] && filtered_repos+=("$repo")
done

repositories=("${filtered_repos[@]}")


if [[ "$DRY_RUN" == "true" ]]; then
for repo in "${repositories[@]}"; do
deploy_to_repo "$repo"
done
return 0
fi

for repo in "${repositories[@]}"; do
if ! deploy_to_repo "$repo"; then
failed_repositories+=("$repo")
exit 1;
else
updated_repositories+=("$repo")
fi
echo >&2
done
}

# Script execution
main