Buforowanie pakietów APT w przepływie pracy Akcje GitHub

9

W moim projekcie C używam następującego przepływu pracy Akcje Github. Przepływ pracy kończy się w około 40 sekund, ale ponad połowa tego czasu jest poświęcana na instalację valgrindpakietu i jego zależności.

Wierzę, że buforowanie może pomóc mi przyspieszyć przepływ pracy. Nie mam nic przeciwko czekaniu kilku dodatkowych sekund, ale wydaje się to bezcelowe marnowanie zasobów GitHub.

name: C Workflow

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1

    - name: make
      run: make

    - name: valgrind
      run: |
        sudo apt-get install -y valgrind
        valgrind -v --leak-check=full --show-leak-kinds=all ./bin

Uruchamianie sudo apt-get install -y valgrindinstaluje następujące pakiety:

  • gdb
  • gdbserver
  • libbabeltrace1
  • libc6-dbg
  • libipt1
  • valgrind

Wiem, że Akcje obsługują buforowanie określonego katalogu (i jest już kilka odpowiedzi na SO pytania i artykuły na ten temat), ale nie jestem pewien, gdzie kończą się wszystkie różne pakiety instalowane przez apt. Przypuszczam, że /bin/albo /usr/bin/nie są jedynymi katalogi dotknięte instalacji pakietów.

Czy istnieje elegancki sposób buforowania zainstalowanych pakietów systemowych na potrzeby przyszłych przepływów pracy?

natiiix
źródło

Odpowiedzi:

5

Celem tej odpowiedzi jest pokazanie, w jaki sposób buforowanie można wykonać za pomocą akcji github. Niekoniecznie musi pokazywać, jak buforować valgrind, co pokazuje, ale także, aby pokazać, że nie wszystko można / należy buforować, i należy wziąć pod uwagę kompromisy buforowania i przywracania bufora w porównaniu z ponowną instalacją zależności.


Wykorzystasz actions/cache akcji.

Dodaj go jako krok (zanim będziesz musiał użyć valgrind):

- name: Cache valgrind
  uses: actions/[email protected]
  id: cache-valgrind
  with:
      path: "~/valgrind"
      key: ${{secrets.VALGRIND_VERSION}}

Następnym krokiem powinna być próba zainstalowania wersji buforowanej, jeśli taka istnieje, lub instalacji z repozytoriów:

- name: Install valgrind
  env:
    CACHE_HIT: ${{steps.cache-valgrind.outputs.cache-hit}}
    VALGRIND_VERSION: ${{secrets.VALGRIND_VERSION}}
  run: |
      if [[ "$CACHE_HIT" == 'true' ]]; then
        sudo cp --verbose --force --recursive ~/valgrind/* /
      else
        sudo apt-get install --yes valgrind="$VALGRIND_VERSION"
        mkdir -p ~/valgrind
        sudo dpkg -L valgrind | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
      fi

Wyjaśnienie

Ustaw VALGRIND_VERSIONsekret jako wynik:

apt-cache policy valgrind | grep -oP '(?<=Candidate:\s)(.+)'

pozwoli to unieważnić pamięć podręczną po wydaniu nowej wersji, zmieniając po prostu wartość tajnego klucza.

dpkg -L valgrindsłuży do wyświetlenia listy wszystkich plików zainstalowanych podczas używania sudo apt-get install valgrind.

To, co możemy teraz zrobić za pomocą tego polecenia, to skopiować wszystkie zależności do naszego folderu pamięci podręcznej:

dpkg -L valgrind | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/

Ponadto

Oprócz skopiowania wszystkich składników valgrindmoże być również konieczne skopiowanie zależności (tak jak libcw tym przypadku), ale nie zalecam kontynuowania tej ścieżki, ponieważ łańcuch zależności po prostu rośnie. Mówiąc ściślej, zależności potrzebne do skopiowania, aby ostatecznie stworzyć środowisko odpowiednie dla valgrinda, są następujące:

  • libc6
  • libgcc1
  • gcc-8-base

Aby skopiować wszystkie te zależności, możesz użyć tej samej składni jak powyżej:

for dep in libc6 libgcc1 gcc-8-base; do
    dpkg -L $dep | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
done

Czy cała ta praca naprawdę jest warta kłopotów, gdy wszystko, co jest wymagane do zainstalowania, valgrindto po prostu uruchomienie sudo apt-get install valgrind? Jeśli Twoim celem jest przyspieszenie procesu kompilacji, musisz również wziąć pod uwagę czas potrzebny do przywrócenia (pobierania i rozpakowywania) pamięci podręcznej w porównaniu z ponownym uruchomieniem polecenia, aby zainstalować valgrind.


Na koniec, aby przywrócić pamięć podręczną, zakładając, że jest ona przechowywana /tmp/valgrind, możesz użyć polecenia:

cp --force --recursive /tmp/valgrind/* /

Który w zasadzie skopiuje wszystkie pliki z pamięci podręcznej na partycję główną.

Oprócz powyższego procesu mam również przykład „buforowania valgrind” poprzez instalację i kompilację ze źródła. Pamięć podręczna ma teraz rozmiar około 63 MB (skompresowany) i nadal trzeba osobno zainstalować, libcktóry rodzaj tego celu nie spełnia .


Bibliografia:

smac89
źródło
Och, rozumiem, to genialne. Nie miałem pojęcia, że ​​możesz bezpiecznie zabrać wszystkie zainstalowane pliki i po prostu przenieść je do innego katalogu, nie psując niczego. Nie jestem pewien, czy to działa. Uruchomiłem przepływ pracy 3 razy i zawsze idę Cache not found for input keys: ***.. Dodałem VALGRIND_VERSIONsekret w Ustawieniach> Sekrety, prawda?
natiiix,
Udało mi się teraz uzyskać trafienie w pamięć podręczną, ale otrzymuję następujący błąd od valgrind:--2906-- Reading syms from /lib/x86_64-linux-gnu/ld-2.27.so --2906-- Considering /lib/x86_64-linux-gnu/ld-2.27.so .. --2906-- .. CRC mismatch (computed 1b7c895e wanted 2943108a) --2906-- object doesn't have a symbol table
natiiix
@natiiix istnieje możliwość, że buforowanie valgrindsprawiło, że libczależność nie jest instalowana podczas pobierania pamięci podręcznej. Nie jestem teraz w pobliżu monitora, ale sprawdziłem twój błąd i wygląda na to, że jest to błąd w valgrind. Możesz także spróbować zainstalować libc w wersji 6 i sprawdzić, czy to pomoże. Zaktualizuję odpowiedź później dzisiaj
smac89,
Tak, wydaje się, że tak. Jeśli dodam sudo apt-get install -y libc6-dbg, to działa dobrze, ale potem też zacząłem, ponieważ instalacja tego pakietu zajmuje 30 sekund.
natiiix,
@natiiix Wygląda na to, że buforowanie valgrind może wymagać więcej pracy niż się spodziewano, ale przynajmniej pokazuje to, jak buforowanie można wykonać na Ubuntu. Patrząc na zależności valgrind, istnieje co najmniej 6 zależności i myślę, że prawdopodobnie wszystkie muszą być buforowane, jeśli to zadziała.
smac89,
4

Możesz utworzyć obraz dokera z valgrindpreinstalowanym i uruchomić na nim przepływ pracy.

Utwórz Dockerfilez czymś takim jak:

FROM ubuntu

RUN apt-get install -y valgrind

Zbuduj go i prześlij do dockerhub:

docker build -t natiiix/valgrind .
docker push natiiix/valgrind

Następnie jako przepływu pracy użyj czegoś takiego:

name: C Workflow

on: [push, pull_request]

jobs:
  build:
    container: natiiix/valgrind

    steps:
    - uses: actions/checkout@v1

    - name: make
      run: make

    - name: valgrind
      run: valgrind -v --leak-check=full --show-leak-kinds=all ./bin

Całkowicie niesprawdzone, ale masz pomysł.

deivid
źródło
Jest to bardzo interesujący pomysł, ale podważa całą zasadę pozwalania Akcjom GitHub buforować środowisko / artefakty dla przyszłych uruchomień i zamiast tego wymaga dodatkowego wysiłku z mojej strony. Z drugiej strony, raz zrobione, prawdopodobnie można z łatwością ponownie wykorzystać.
natiiix
1
To Ty decydujesz, co będzie dla Ciebie najlepsze lub co będzie najbardziej obraźliwe z twojej strony ¯_ (ツ) _ / ¯
deivid