Armazenando em cache pacotes APT no fluxo de trabalho Ações do GitHub

9

Eu uso o seguinte fluxo de trabalho Ações do Github para o meu projeto em C. O fluxo de trabalho termina em ~ 40 segundos, mas mais da metade desse tempo é gasto instalando o valgrindpacote e suas dependências.

Acredito que o cache poderia me ajudar a acelerar o fluxo de trabalho. Não me importo de esperar mais alguns segundos, mas isso parece um desperdício inútil dos recursos do 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

A execução sudo apt-get install -y valgrindinstala os seguintes pacotes:

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

Eu sei que o Actions suporta o cache de um diretório específico (e já existem várias perguntas e artigos sobre SO) sobre isso, mas não tenho certeza de onde todos os diferentes pacotes instalados pelo apt terminam. Presumo /bin/ou /usr/bin/não somos os únicos diretórios afetados pela instalação de pacotes.

Existe uma maneira elegante de armazenar em cache os pacotes do sistema instalados para futuras execuções do fluxo de trabalho?

natiiix
fonte

Respostas:

5

O objetivo desta resposta é mostrar como o cache pode ser feito com ações do github. Não necessariamente para mostrar como armazenar em cache valgrind, o que mostra, mas também para mostrar que nem tudo pode / deve ser armazenado em cache, e as vantagens e desvantagens de armazenar em cache e restaurar um cache versus reinstalar a dependência precisam ser levadas em consideração.


Você fará uso da actions/cacheação para fazer isso.

Adicione-o como uma etapa (antes de precisar usar o valgrind):

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

A próxima etapa deve tentar instalar a versão em cache, se houver, ou instalar a partir dos repositórios:

- 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

Explicação

Defina VALGRIND_VERSIONsegredo para ser a saída de:

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

isso permitirá que você invalide o cache quando uma nova versão for lançada simplesmente alterando o valor do segredo.

dpkg -L valgrindé usado para listar todos os arquivos instalados ao usar sudo apt-get install valgrind.

O que podemos agora fazer com este comando é copiar todas as dependências para nossa pasta de cache:

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

além disso

Além de copiar todos os componentes de valgrind, também pode ser necessário copiar as dependências (como libcneste caso), mas não recomendo continuar nesse caminho porque a cadeia de dependências cresce a partir daí. Para ser preciso, as dependências necessárias para copiar para finalmente ter um ambiente adequado para execução do valgrind são as seguintes:

  • libc6
  • libgcc1
  • gcc-8-base

Para copiar todas essas dependências, você pode usar a mesma sintaxe que acima:

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 esse trabalho realmente vale a pena quando tudo o que é necessário para instalar valgrindem primeiro lugar é simplesmente executar sudo apt-get install valgrind? Se seu objetivo é acelerar o processo de compilação, também é necessário levar em consideração a quantidade de tempo que leva para restaurar (baixar e extrair) o cache e simplesmente executar o comando novamente para instalar valgrind.


E, finalmente, para restaurar o cache, assumindo que ele esteja armazenado em /tmp/valgrind, você pode usar o comando:

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

O que basicamente copiará todos os arquivos do cache para a partição raiz.

Além do processo acima, também tenho um exemplo de "cache valgrind" instalando e compilando-o da fonte. O cache agora tem cerca de 63 MB (compactado) de tamanho e ainda é necessário instalar separadamente, libcque derruba o objetivo.


Referências:

smac89
fonte
Oh, entendo, isso é engenhoso. Eu não tinha idéia de que você poderia pegar com segurança todos os arquivos instalados e apenas movê-los para outro diretório sem quebrar nada. Não tenho certeza se funciona. Eu executei o fluxo de trabalho três vezes e sempre vou Cache not found for input keys: ***.. Eu adicionei o VALGRIND_VERSIONsegredo em Configurações> Segredos, está certo?
Natiiix 11/12/19
Eu consegui obter um acerto de cache agora, mas estou recebendo o seguinte erro do 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 11/11/19
@natiiix, existe a possibilidade de o cache ter valgrindfeito com que a libcdependência não seja instalada quando o cache for recuperado. Não estou perto de um monitor agora, mas procurei seu erro e parece que é um bug do valgrind. Você também pode tentar instalar a libc versão 6 e ver se isso ajuda. Atualizarei a resposta hoje mais tarde
smac89
Sim, parece que sim. Se eu adicionar sudo apt-get install -y libc6-dbg, ele funcionará bem, mas também estou onde comecei porque a instalação desse pacote leva mais 30 segundos.
Natiiix 11/12/19
@natiiix Parece que o cache do valgrind pode ser mais trabalhoso do que o previsto, mas pelo menos isso mostra como o cache pode ser feito no ubuntu. Observando as dependências do valgrind, existem pelo menos 6 dependências e acho que todas elas provavelmente precisam ser armazenadas em cache para que isso funcione.
smac89
4

Você pode criar uma imagem de janela de encaixe valgrindpré - instalada e executar seu fluxo de trabalho nela.

Crie um Dockerfilecom algo como:

FROM ubuntu

RUN apt-get install -y valgrind

Construa-o e envie-o para o dockerhub:

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

Em seguida, use algo como o seguinte como seu fluxo de trabalho:

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 não testado, mas você entendeu.

deivid
fonte
Essa é uma ideia muito interessante, mas que compromete todo o princípio de permitir que o GitHub Actions armazene em cache o ambiente / artefatos para futuras execuções e, em vez disso, requer algum esforço adicional do meu lado. Por outro lado, uma vez feito, isso provavelmente poderia ser reutilizado com bastante facilidade.
natiiix 30/03
11
Cabe a você decidir o que funciona melhor para você ou o que exige o maior número de desvios do seu lado ¯_ (ツ) _ / ¯
deivid