Almacenamiento en caché de paquetes APT en el flujo de trabajo de acciones de GitHub

9

Utilizo el siguiente flujo de trabajo de Github Actions para mi proyecto C. El flujo de trabajo finaliza en ~ 40 segundos, pero se pasa más de la mitad de ese tiempo instalando el valgrindpaquete y sus dependencias.

Creo que el almacenamiento en caché podría ayudarme a acelerar el flujo de trabajo. No me importa esperar un par de segundos extra, pero esto parece una pérdida inútil de los recursos de 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

Running sudo apt-get install -y valgrindinstala los siguientes paquetes:

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

Sé que Actions admite el almacenamiento en caché de un directorio específico (y ya hay varias preguntas y artículos SO resueltos sobre esto), pero no estoy seguro de dónde terminan todos los diferentes paquetes instalados por apt. Asumo /bin/o /usr/bin/no son los únicos directorios afectados por la instalación de paquetes.

¿Existe una manera elegante de almacenar en caché los paquetes del sistema instalados para futuras ejecuciones de flujo de trabajo?

natiiix
fuente

Respuestas:

5

El propósito de esta respuesta es mostrar cómo se puede hacer el almacenamiento en caché con acciones de github. No necesariamente para mostrar cómo almacenar en caché valgrind, lo que sí muestra, sino también para mostrar que no todo puede / debe almacenarse en caché, y las compensaciones del almacenamiento en caché y la restauración de un caché frente a la reinstalación de la dependencia deben tenerse en cuenta.


Harás uso de la actions/cacheacción para hacer esto.

Añádalo como un paso (antes de que necesite usar valgrind):

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

El siguiente paso debe intentar instalar la versión en caché, si la hay, o instalar desde los repositorios:

- 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

Explicación

Establecer VALGRIND_VERSIONsecreto para ser la salida de:

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

esto le permitirá invalidar el caché cuando se lance una nueva versión simplemente cambiando el valor del secreto.

dpkg -L valgrindse usa para enumerar todos los archivos instalados cuando se usa sudo apt-get install valgrind.

Lo que ahora podemos hacer con este comando es copiar todas las dependencias a nuestra carpeta de caché:

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

además

Además de copiar todos los componentes de valgrind, también puede ser necesario copiar las dependencias (como libcen este caso), pero no recomiendo continuar a lo largo de esta ruta porque la cadena de dependencia simplemente crece a partir de ahí. Para ser precisos, las dependencias necesarias para copiar para finalmente tener un entorno adecuado para que valgrind se ejecute son las siguientes:

  • libc6
  • libgcc1
  • gcc-8-base

Para copiar todas estas dependencias, puede usar la misma sintaxis que la anterior:

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

¿Todo este trabajo realmente vale la pena cuando todo lo que se requiere para instalar valgrinden primer lugar es simplemente ejecutar sudo apt-get install valgrind? Si su objetivo es acelerar el proceso de compilación, también debe tener en cuenta la cantidad de tiempo que lleva restaurar (descargar y extraer) el caché en lugar de simplemente ejecutar el comando nuevamente para instalar valgrind.


Y finalmente para restaurar el caché, suponiendo que esté almacenado en /tmp/valgrind, puede usar el comando:

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

Que básicamente copiará todos los archivos del caché a la partición raíz.

Además del proceso anterior, también tengo un ejemplo de "almacenamiento en caché de valgrind" al instalarlo y compilarlo desde la fuente. El caché ahora tiene un tamaño de aproximadamente 63 MB (comprimido) y aún se necesita instalar por separado libcqué tipo de objetivo falla .


Referencias

smac89
fuente
Oh, ya veo, eso es ingenioso. No tenía idea de que podría tomar con seguridad todos los archivos instalados y simplemente moverlos a otro directorio sin romper algo. Sin embargo, no estoy seguro de que funcione. Ejecuté el flujo de trabajo 3 veces y siempre voy Cache not found for input keys: ***.. Agregué el VALGRIND_VERSIONsecreto en Configuración> Secretos, ¿es así?
natiiix
Me las arreglé para obtener un acierto de caché ahora, pero recibo el siguiente error de 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 existe la posibilidad de que el almacenamiento en caché lo valgrindhaga de modo que la libcdependencia no se instale cuando se recupere el caché. Ahora no estoy cerca de un monitor, pero busqué su error y parece que es un error con valgrind. También puede intentar instalar libc versión 6 y ver si eso ayuda. Actualizaré la respuesta más tarde hoy
smac89
Sí, eso parece. Si agrego sudo apt-get install -y libc6-dbg, entonces funciona bien, pero también estoy donde comencé porque la instalación de ese paquete tarda 30 segundos más.
natiiix
@natiiix Parece que el almacenamiento en caché de valgrind puede ser más trabajo de lo previsto, pero al menos esto muestra cómo se puede hacer el almacenamiento en caché en ubuntu. Mirando las dependencias de valgrind, hay al menos 6 dependencias, y creo que probablemente todas necesiten ser almacenadas en caché para que esto funcione.
smac89
4

Puede crear una imagen acoplable con valgrindpreinstalado y ejecutar su flujo de trabajo en eso.

Crea un Dockerfilecon algo como:

FROM ubuntu

RUN apt-get install -y valgrind

Construirlo y empujarlo a dockerhub:

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

Luego use algo como lo siguiente como flujo de trabajo:

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

Completamente no probado, pero entiendes la idea.

deivid
fuente
Esta es una idea muy interesante, pero menoscaba el principio de dejar que GitHub Actions guarde en caché el entorno / artefactos para futuras ejecuciones y, en cambio, requiere un esfuerzo adicional de mi parte. Por otro lado, una vez hecho esto, probablemente podría reutilizarse con bastante facilidad.
natiiix
1
Depende de usted decidir qué funciona mejor para usted, o qué requiere la mayor cantidad de trabajo de su lado ¯_ (ツ) _ / ¯
deivid