Jak usunąć kompilacje 11 do 1717 w Jenkins?

51

Z powodu błędnej konfiguracji mam ponad 1700 nieudanych kompilacji w zadaniu Jenkinsa.

Jak mogę je skutecznie wyczyścić?

Aaron Digulla
źródło
2
Omówiono tutaj kilka sposobów usuwania kompilacji za pomocą wiersza polecenia: stackoverflow.com/questions/13052390/…
ThomasW

Odpowiedzi:

74

Masz kilka opcji:

  • Tymczasowo ustaw liczbę kompilacji, które mają pozostać w konfiguracji zadania ( Odrzuć stare kompilacje), aby kompilacje te zostały usunięte po zakończeniu następnej kompilacji. Jeśli następna kompilacja to 1800, ustaw ją tak, aby zachować najnowszą 85 lub mniej. Zaznacz wszystkie starsze wersje (tj. Od 1 do 10) jako Zachowaj tę wersję na zawsze przed rozpoczęciem kolejnej wersji. Ta opcja nie usunie niektórych kompilacji, jeśli masz zadanie, które zapobiega usuwaniu kompilacji (nie jest to problem w twojej sytuacji, jeśli wszystkie z nich zawiodły).

  • Użyj konsoli skryptów w Zarządzaj Jenkins . Jeśli jest to zadanie najwyższego poziomu (nie ma go w folderze), załatwi sprawę:

    Jenkins.instance.getItemByFullName('JobName').builds.findAll { it.number > 10 && it.number < 1717 }.each { it.delete() }

    Oczywiście to podejście wymaga na ogół dobrych kopii zapasowych. Za pomocą konsoli skryptów możesz wiele zepsuć.

  • Usuń foldery kompilacji z dysku (domyślnie $JENKINS_HOME/jobs/JobName/builds/za pomocą znacznika czasu rozpoczęcia jako nazwy folderu) i uruchom ponownie Jenkins lub Załaduj ponownie konfigurację z dysku . Ta opcja nie zezwala na wtyczki, które np. Utrzymują porządek w historii SVN, przenosząc wszelkie zmiany do kolejnej wersji, aby wykonać swoje zadanie.

Daniel Beck
źródło
10
Znalazłem inne rozwiązanie: Korzystaniejenkins-cli.jar -s ... delete-builds envjs 11-1717
Aaron Digulla
Zrobiono listę, aby wyświetlić listę wszystkich zadań z liczbą kompilacji za pośrednictwem terminala. Ułatwia znalezienie pracy, która wymaga oczyszczenia. Może być również używany przez cron jako raport e-mail.
Nick
@Nick Sprawdź wtyczkę Groovy, w szczególności systemowy typ kroku Groovy. Nie musisz w tym celu wychodzić poza Jenkins, po prostu stwórz pracę, która to zrobi. jenkins.model.Jenkins.instance.getAllItems(hudson.model.Job.class).each { println it.fullDisplayName + " has " + it.builds.size() + " builds" } ; returnSortowanie np. Według kompilacji jest podobnie trywialne.
Daniel Beck
W przypadku potoków rozgałęzionych można użyć składni JobName/branch
waitinforatrain
17

Wystarczy wykonać połączenie API:

curl -X POST http://jenkinUser:[email protected]/job/theJob/[11-1717]/doDelete

Aby uzyskać APIToken: zaloguj się do Jenkins> Konfiguracja> Pokaż token API.

cześć
źródło
Myślę, że to najlepsze podejście do problemu. można go wykonać zdalnie, a dzięki REST zapewnia szeroki zakres działań
alfredocambera
Najlepsza odpowiedź, ponieważ nie musisz szukać słoika w zainstalowanym systemie.
Keith Tyler
Miałem na myśli „nie musisz niczego pobierać”
Keith Tyler,
„Najlepsza odpowiedź, ponieważ nie musisz” - jeśli twoim kryterium nie jest pobranie pliku <1m, lepiej jest podziękować CLI. Jeśli kryterium nie wymaga wpisywania niechlujnych adresów URL za pomocą tokenów uwierzytelniania, pamiętaj o składni curl (zakładając, że jest on instalowany w pierwszej kolejności), a wolisz jasne polecenia i pomaga, a może masz już słoik, CLI jest lepszy. Jeśli masz tylko interfejs my z zainstalowaną konsolą skryptową, to ta jest lepsza. Jak zwykle to zależy.
user17265
w przypadku usuwania zachowaj zawsze kompilacje, uruchom toggleLogKeepwcześniej doDelete.
Fancyoung
16

Jak poprawnie stwierdził Aaron , w tym celu możesz również użyć interfejsu CLI Jenkinsa :

java -jar jenkins-cli.jar -s http://yourserver.com delete-builds <JobName> 11-1717
Jaltek
źródło
4

Szablon skryptu do uruchomienia w konsoli Jenkins Script-Console. Użyj flagi, reallyDeleteaby ją przetestować przed faktycznym usunięciem:

// Jenkins job
def jobName = 'foo'
// Range of builds to delete
def rs = Fingerprint.RangeSet.fromString("11-1717", false);
// Set to true to actually delete. Use false to test the script.
def reallyDelete = false;

// ----------------------------------
def job = Jenkins.instance.getItemByFullName(jobName);
println("Job: ${job.fullName}");

def builds = Jenkins.instance.getItemByFullName(jobName).getBuilds(rs);
println("Found ${builds.size()} builds");
builds.each{ b-> 
  if (reallyDelete) {
    println("Deleting ${b}");
    b.delete();
  } else {
    println("Found match ${b}");
  }
}
Aaron Digulla
źródło
1

To samo zadanie napotkałem, kiedy przejąłem serwer Jenkins, na którym jest nieco ponad 150 zadań z nawet 3000 starszymi kompilacjami, więc napisałem mały skrypt bash, który zachowuje tylko 10 ostatnich kompilacji:

#! /bin/bash

initialPath=$(pwd);

find /var/lib/jenkins/ -type d -name builds | while read jobs
 do

    #############################################################
    ## Enter build-directory of current job and get some numbers
    #############################################################
    cd "$jobs" ;
    ls -d [[:digit:]]* &>/dev/null ;
    rc=$? ;
    if [[ $rc -eq 0 ]] ;
     then
        buildName=$(ls -d [[:digit:]]*)  ;
        latestBuild=$(echo $buildName | awk '{print $NF}') ; # highest number
        oldestBuild=$(echo $buildName | awk '{print $1}') ; # lowest number
        amountOfBuilds=$(echo $buildName | wc -w ) ;
        lastBuildToKeep=$(echo "${latestBuild} 9" | awk '{print $1 - $2}') ;

        ############################################################
        ## Skip Folder if it contains less than 10 builds
        ############################################################
        if [ ${amountOfBuilds} -le 10 ] ;
         then
            echo "Skipping $(pwd) --> less than 10 builds";
         else
            ############################################################
            ## Delete all build-directories except the last 10
            ############################################################
            for (( i=$oldestBuild; i<$lastBuildToKeep; i++))
             do
                echo "Deleting $(pwd)/${i} ..."
                rm -r "$i" ;
            done ;
        fi ;
     else
        echo "Skipping $(pwd) --> Zero builds";
    fi ;
done ;

############################################################
## go back to $initialPath
############################################################
cd "$initialPath" ;

Ponowne uruchomienie Jenkinsa później jest wysoce zalecane, aby uniknąć problemów. Dzięki @Aaron Digulla

Anyesto
źródło
Dlaczego nie użyłeś skryptu dla konsoli Jenkins?
Aaron Digulla
Ponieważ jestem bardziej zaznajomiony z bash. To jedyny powód.
Anyesto
Zrozumiany. Edytuj swoje pytanie i dodaj, że Jenkins musi zostać ponownie uruchomiony, aby uniknąć problemów.
Aaron Digulla
0

Stworzyłem mały skrypt Pythona, który służyłby temu celowi. Oto skrypt:

delete_jenkins_builds.py

from os import listdir, path
import shutil


job_build_fullpath = '/var/lib/jenkins/jobs/My-Jenkins-Project/builds'
print listdir(job_build_fullpath)

for build_dir in listdir(job_build_fullpath):
        if build_dir.isdigit() and int(build_dir) in range(11, 1718):
                build_dir_fullpath = path.join(job_build_fullpath, build_dir)
                print "Deleting: " + build_dir_fullpath
                shutil.rmtree(build_dir_fullpath)
  • job_build_fullpath - Ścieżka do katalogu kompilacji zadania

  • range (start_build_no, end_build_no) - zakres (11, 1718) wyszukuje wszystkie kompilacje, począwszy od kompilacji nr. 11 do budowy nr. 1717. Ustaw odpowiednio.

  • shutil.rmtree (katalog_kompilacji_pełny) - usuwa każdy katalog kompilacji, który znajduje się w zakresie.

Wersja Python: 2.7

Shubham Soin
źródło
Czy potem nie będziesz musiał ponownie uruchamiać Jenkinsa? Co jeśli Jenkins przechowuje informacje o tych folderach w bazie danych?
Aaron Digulla
Tak @AaronDigulla, wymagane będzie ponowne uruchomienie serwera Jenkins, aby odzwierciedlić zmiany w portalu Jenkins.
Shubham Soin