Compare commits
No commits in common. "022265419755cb007c26e2864987242f44c19314" and "7442746e5940559d19ba0746d13932616d2272aa" have entirely different histories.
0222654197
...
7442746e59
@ -1,33 +0,0 @@
|
|||||||
name: Workflows
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *' # Every day at midnight
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
wake:
|
|
||||||
name: Wake Runner
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Wakeup Runner
|
|
||||||
run: |
|
|
||||||
curl https://idlesleep.wolproxy.seeseepuff.be/status
|
|
||||||
|
|
||||||
run:
|
|
||||||
name: Run script
|
|
||||||
runs-on: ubuntu-amd64
|
|
||||||
container:
|
|
||||||
image: gitea.seeseepuff.be/archlinux/archlinux:latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Ensure image is up-to-date
|
|
||||||
run: |
|
|
||||||
sudo pacman -Syu --noconfirm
|
|
||||||
|
|
||||||
- name: Run script
|
|
||||||
run: |
|
|
||||||
TOkEN=${{ secrets.TOKEN }} go run .
|
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
/.idea
|
|
||||||
/venv
|
/venv
|
||||||
/.env
|
/.env
|
||||||
/work
|
/work
|
213
autobuilder.go
213
autobuilder.go
@ -1,16 +1,24 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func cloneRepository(repo Repository, workDir string) error {
|
||||||
|
cmd := exec.Command("git", "clone", repo.CloneURL, filepath.Join(workDir, repo.Name))
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to clone %s: %w", repo.Name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
token := os.Getenv("TOKEN")
|
token := os.Getenv("TOKEN")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
@ -39,193 +47,30 @@ func main() {
|
|||||||
log.Fatalf("Failed to get repositories: %v", err)
|
log.Fatalf("Failed to get repositories: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
failedRepos := make([]string, 0)
|
success := true
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
if repo.Template || strings.Contains(repo.Name, "skip-autobuild") {
|
log.Printf("Checking %s", repo.FullName)
|
||||||
// Skip template repositories
|
hasFile, err := client.hasPKGBUILD(repo)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error checking for PKGBUILD: %v", err)
|
||||||
|
success = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
wasRepoProcessed := processRepo(&client, workDir, repo)
|
|
||||||
if !wasRepoProcessed {
|
if !hasFile {
|
||||||
failedRepos = append(failedRepos, repo.Name)
|
log.Println("PKGBUILD not found, skipping")
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := cloneRepository(repo, workDir); err != nil {
|
||||||
|
success = false
|
||||||
|
log.Printf("Error cloning repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(failedRepos) > 0 {
|
if !success {
|
||||||
log.Println("The following repos failed to process:")
|
|
||||||
for _, repo := range failedRepos {
|
|
||||||
log.Printf(" - %s", repo)
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processRepo(client *GiteaClient, workDir string, repo Repository) (success bool) {
|
|
||||||
log.Printf("Checking %s", repo.FullName)
|
|
||||||
hasFile, err := client.hasPKGBUILD(repo)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error checking for PKGBUILD: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasFile {
|
|
||||||
log.Println("PKGBUILD not found, skipping")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
repoPath, err := cloneRepository(client.Token, repo, workDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error cloning repository: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run pre-run script (if it exists)
|
|
||||||
requirePush := false
|
|
||||||
defer func() {
|
|
||||||
if requirePush {
|
|
||||||
err = pushRepository(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error pushing repository: %v", err)
|
|
||||||
success = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
preRunScript := filepath.Join(repoPath, "pre-run.sh")
|
|
||||||
if _, err := os.Stat(preRunScript); !os.IsNotExist(err) {
|
|
||||||
cmd := exec.Command("/bin/sh", "./pre-run.sh")
|
|
||||||
cmd.Dir = workDir
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error running pre-run script: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
requirePush = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the repository is up-to-date
|
|
||||||
upToDate, err := checkUpToDate(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error checking if up to date: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if upToDate {
|
|
||||||
log.Printf("%s is up-to-date, skipping", repo.FullName)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("%s requires bumping, running script", repo.FullName)
|
|
||||||
updated, err := bumpRepository(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error bumping repository: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if updated {
|
|
||||||
requirePush = true
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func cloneRepository(token string, repo Repository, workDir string) (string, error) {
|
|
||||||
targetPath := filepath.Join(workDir, repo.Name)
|
|
||||||
cmd := exec.Command("git", "clone", fmt.Sprintf("https://seeseemelk:%s@gitea.seeseepuff.be/archlinux/%s", token, repo.Name), targetPath)
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to clone %s: %w", repo.Name, err)
|
|
||||||
}
|
|
||||||
return targetPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkUpToDate(repoPath string) (bool, error) {
|
|
||||||
log.Println("Checking if up-to-date")
|
|
||||||
cmd := exec.Command("/bin/sh", "./check-up-to-date.sh", repoPath)
|
|
||||||
output, err := cmd.CombinedOutput()
|
|
||||||
log.Println("Command output: ", string(output))
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("failed to inspect %s: %w", repoPath, err)
|
|
||||||
}
|
|
||||||
if strings.Index(string(output), "UP-TO-DATE") >= 0 {
|
|
||||||
return true, nil
|
|
||||||
} else if strings.Index(string(output), "OUT-OF-DATE") >= 0 {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, errors.New("error parsing command output")
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Finds the line that says "pkgrel=NUMBER" in the repository's PKGBUILD file,
|
|
||||||
and increments the number by 1.
|
|
||||||
*/
|
|
||||||
func bumpRepository(repoPath string) (bool, error) {
|
|
||||||
pkgbuildPath := filepath.Join(repoPath, "PKGBUILD")
|
|
||||||
|
|
||||||
// Read the file
|
|
||||||
content, err := os.ReadFile(pkgbuildPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to read %s: %v", pkgbuildPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(content), "\n")
|
|
||||||
updated := false
|
|
||||||
|
|
||||||
// Iterate through lines to find and update pkgrel
|
|
||||||
for i, line := range lines {
|
|
||||||
if strings.HasPrefix(line, "pkgrel=") {
|
|
||||||
parts := strings.SplitN(line, "=", 2)
|
|
||||||
if len(parts) == 2 {
|
|
||||||
// Parse and increment the pkgrel value
|
|
||||||
pkgrel, err := strconv.Atoi(strings.TrimSpace(parts[1]))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to parse pkgrel value: %v", err)
|
|
||||||
}
|
|
||||||
lines[i] = fmt.Sprintf("pkgrel=%d", pkgrel+1)
|
|
||||||
updated = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !updated {
|
|
||||||
return false, fmt.Errorf("pkgrel line not found in PKGBUILD file")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the updated content back to the PKGBUILD file
|
|
||||||
err = os.WriteFile(pkgbuildPath, []byte(strings.Join(lines, "\n")), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("error writing updated PKGBUILD file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("PKGBUILD updated, creating commit")
|
|
||||||
|
|
||||||
// Create commit
|
|
||||||
cmd := exec.Command("git", "commit", "PKGBUILD", "-m", "Bump pkgrel")
|
|
||||||
cmd.Dir = repoPath
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("failed to commit changes: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func pushRepository(repoPath string) error {
|
|
||||||
// Push commit
|
|
||||||
log.Println("Pushing commit")
|
|
||||||
cmd := exec.Command("git", "push")
|
|
||||||
cmd.Dir = repoPath
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to push changes: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("Successfully bumped pkgrel in PKGBUILD")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Exit on any error
|
|
||||||
set -e
|
|
||||||
|
|
||||||
cd $1
|
|
||||||
|
|
||||||
# Source the PKGBUILD in a subshell to avoid polluting the global environment
|
|
||||||
(
|
|
||||||
source ./PKGBUILD
|
|
||||||
|
|
||||||
# Convert pkgname to array in case it's a single string
|
|
||||||
pkgnames=("${pkgname[@]}")
|
|
||||||
|
|
||||||
for pkg in "${pkgnames[@]}"; do
|
|
||||||
echo "Checking package: $pkg"
|
|
||||||
|
|
||||||
if pacman -Si "$pkg" &>/dev/null; then
|
|
||||||
echo "Package '$pkg' exists in a repository."
|
|
||||||
|
|
||||||
# Get the package build date
|
|
||||||
pkg_build_date=$(date -d "$(pacman -Si "$pkg" | grep 'Build Date' | cut -d: -f2-)" +%s)
|
|
||||||
|
|
||||||
all_deps=("${depends[@]}" "${makedepends[@]}" "${optdepends[@]}")
|
|
||||||
|
|
||||||
# Check each dependency
|
|
||||||
for dep in "${all_deps[@]}"; do
|
|
||||||
dep_name=$(echo "$dep" | sed 's/[<>=].*//') # Remove version constraints
|
|
||||||
echo "Querying dependency: $dep_name"
|
|
||||||
|
|
||||||
if pacman -Si "$dep_name" &>/dev/null; then
|
|
||||||
dep_build_date=$(date -d "$(pacman -Si "$dep_name" | grep 'Build Date' | cut -d: -f2-)" +%s)
|
|
||||||
if (( dep_build_date >= pkg_build_date )); then
|
|
||||||
echo "Dependency '$dep_name' has newer or equal build date than '$pkg'."
|
|
||||||
echo "OUT-OF-DATE"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Dependency '$dep_name' not found in repositories. Skipping."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "All dependencies are older than package '$pkg'."
|
|
||||||
echo "UP-TO-DATE"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "Package '$pkg' does NOT exist in any repository."
|
|
||||||
echo "OUT-OF-DATE"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
)
|
|
10
gitea.go
10
gitea.go
@ -14,12 +14,10 @@ type GiteaClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Repository struct {
|
type Repository struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
CloneURL string `json:"clone_url"`
|
CloneURL string `json:"clone_url"`
|
||||||
Owner Owner `json:"owner"`
|
Owner Owner `json:"owner"`
|
||||||
FullName string `json:"full_name"`
|
FullName string `json:"full_name"`
|
||||||
Template bool `json:"template"`
|
|
||||||
Topics []string `json:"topics"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Owner struct {
|
type Owner struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user