Incluindo os resultados de teste e os scripts de construção no pipeline

Conecte seu fluxo de teste e construção existente ao pipeline de integração contínua adicionando os resultados de seus scripts de teste e construção novos ou existentes ao fluxo de integração contínua do pipeline DevSecOps.

No início do pipeline, os scripts do DevSecOps clonam automaticamente os repositórios de aplicativos e de configuração nos seguintes diretórios:

  1. O repositório do aplicativo é clonado no caminho /workspace/app/<APP_REPO_NAME>

  2. O repositório de configuração do pipeline é clonado no caminho /workspace/app/one-pipeline-config-repo

Em qualquer estágio, se você precisar executar scripts localizados nesses repositórios, deverá primeiro navegar até os diretórios apropriados. Você pode fazer isso usando um dos seguintes métodos:

  1. Usar os caminhos do repositório clonado diretamente
  • Repositório de aplicativos: cd "${WORKSPACE}/$APP_REPO_NAME"

  • Repositório de configuração: cd "${WORKSPACE}/one-pipeline-config-repo/"

  1. Usando o comando load_repo
  • Repositório de aplicativos: cd "${WORKSPACE}/$(load_repo app-repo path)"

  • Repositório de configuração: cd "${WORKSPACE}/$(load_repo one-pipeline-config-repo path)"

$WORKSPACE refere-se ao caminho raiz /workspace/app.

Os estágios a seguir podem ser utilizados no pipeline de integração contínua para inclusão de etapas de teste e construção:

  • Instalação
  • Teste
  • Containerize (construção)
  • Liberação

Configuração do pipeline

Use o estágio Setup para configurar seu ambiente de teste e compilação e extrair informações para o pipeline. Por exemplo, vários repositórios relacionados ao aplicativo podem ser usados em uma única construção. Você pode clonar todos os repositórios de que precisa e tornar o pipeline ciente desses repositórios em verificações e varreduras relacionadas à conformidade.

O repositório de aplicativos padrão que é clonado internamente pelo pipeline e adicionado ao pipeline usando a interface save_repo pipelinectl com o nome de referência app-repo. O repositório padrão é fornecido pelo parâmetro de IU do pipeline de repositório ou selecionado por seu nome de ligação da cadeia de ferramentas, caso o pipeline tenha sido configurado a partir do modelo de cadeia de ferramentas.

Se você quiser usar mais repositórios, clone-os no estágio de configuração e use a mesma interface save_repo para adicioná-los ao pipeline.

Exemplo

#
# your scripts cloning the repositories
#
# make sure you prepare or export the following data from each cloned repository:
# - repository URL
# - path where it was cloned, relative to the $WORKSPACE path
# - cloned branch
# - latest commit hash
#
your_clone_scripts

#
# when cloning is complete
# use `save_repo` to add these information to the pipeline
# repo-reference-name can be any name, it is used to refer to the stored repo
#
save_repo <repo-reference-name> \
    url="${REPO_URL}" \
    path="${REPO_PATH}" \
    branch="${CLONED_BRANCH}" \
    commit="${LATEST_GIT_COMMIT}"

Dessa forma, o restante do pipeline pode fazer a varredura desses repositórios em busca de violações de conformidade e vulnerabilidades.

Os caminhos que são salvos usando save_repo devem ser relativos ao caminho do espaço de trabalho.

Não é necessário instalar a ferramenta pipelinectl para seus scripts ou imagens de base; o pipeline de referência fornece os arquivos binários para o contexto do script.

Testar

Este é o estágio em que são executados os testes nos repositórios de códigos. Você pode acessar os repositórios adicionados no estágio de configuração usando as interfaces list_repos e load_repo pipelinectl.

Exemplo

exit_code=0

#
# `list_repos` returns the list of the reference names of saved repos
#
list_repos | while IFS= read -r repository ; do

    #
    # load_repo returns a property of a saved repository
    #
    # Usage:
    # load_repo <repo-reference-name> <property>
    #
    url="$(load_repo "$repository" url)"
    sha="$(load_repo "$repository" commit)"
    branch="$(load_repo "$repository" branch)"
    path="$(load_repo "$repository" path)"

    #
    # use your repos to test, etc
    #
    run_tests
    result=$?

    if [ $result != 0 ]; then
        exit_code=$result
    fi
done

exit $exit_code

O controle de conformidade do teste de unidade é baseado no código de saída do script de estágio. Se os seus testes forem aprovados, saia com 0. Se não, retorne um código de saída diferente de zero no final.

Salvando os resultados

Seus testes podem gerar alguns artefatos de relatório, como resultados de teste em JSON ou XML. Use a interface save_result pipelinectl neste estágio para anexar os testes à evidência de conformidade criada como artefatos de evidência de evidência.

#
# run tests with some test suite runner, and save output to results.json
#
test_runner -o results.json

#
# save the result for the pipeline, so it can attach it to the unit test evidence
#
save_result test results.json

O primeiro parâmetro de save_results deve ser o nome do estágio config do pipeline do DevSecOps, como test, scan-artifact ou acceptance-test. Caso contrário, o coletor de provas não conseguirá encontrá-lo e anexá-lo à peça de prova adequada.

O uso da interface save_result pipelinectl garante que o pipeline encontre seus artefatos de resultado, que eles sejam carregados no armário de evidências e anexados às evidências de conformidade criadas pelo pipeline.

Evidência de exemplo criada para os testes de unidade ao utilizar save_result:

{
  "evidence_type_id": "com.ibm.unit_tests",
  "evidence_type_version": "1.0.0",
  "date": "2021-03-31T07:41:31.881Z",
  "result": "success",
  "pipeline_id": "8c2b6750-91db-45fb-98ee-51684843b821",
  "pipeline_run_id": "89a04de9-2795-4e8e-be90-52a92ac7f9c1",
  "issues": [],
  "artifacts": [
    {
      "url": "https://s3.us-south.cloud-object-storage.appdomain.cloud/cos-bucket-name/ci/89a04de9-2795-4e8e-be90-52a92ac7f9c1/artifacts/compliance-app-COMPACT-20210218231513608/unit-tests-results.json_d9619521e7444fef0ff052e59fd54049",
      "hash": "d9619521e7444fef0ff052e59fd54049"
    }
  ],
  "toolchain_crn": "crn:v1:bluemix:public:toolchain:us-south:a/40111714589c4f7099032529b26a7a63:39d4f080-55e5-42ee-a787-26d936fb2b97::",
  "log": [
    {
      "url": "https://cloud.ibm.com/devops/pipelines/tekton/8c2b6750-91db-45fb-98ee-51684843b821/runs/89a04de9-2795-4e8e-be90-52a92ac7f9c1/code-unit-tests/run-stage?env_id=ibm:yp:us-south",
      "hash": null
    },
    {
      "url": "https://s3.us-south.cloud-object-storage.appdomain.cloud/cos-bucket-name/ci/89a04de9-2795-4e8e-be90-52a92ac7f9c1/artifacts/logs/code-unit-tests/run-stage.log_dae902fb1455b1fc9c565273aa4fe1bc",
      "hash": "dae902fb1455b1fc9c565273aa4fe1bc"
    }
  ]
}

Construção ou conteinerização

Nesta etapa, você pode criar seus artefatos. O pipeline fornece alguns recursos padrão para artefatos do tipo imagem do docker, mas você pode criar qualquer artefato aqui. Salve os artefatos criados para o pipeline, para que posteriormente ele possa executar varreduras nele ou usar os artefatos em seu estágio de liberação.

Para fornecer informações sobre os artefatos construídos, use a interface de pipelinectl save_artifact .

Exemplo

#
# your scripts building the artifact
#
# make sure you prepare or export the following data from each built artifact:
# - type (image for docker images, package for rpms, npm tarballs, etc )
# - full artifact URL with version tag
# - artifact digest
#
your_build_scripts

#
# when the build is complete
# use `save_artifact` to add these information to the pipeline
# artifact-reference-name can be any name, it is used to refer to the stored artifact
#
save_artifact <artifact-reference-name> \
    type=image" \
    name="${IMAGE_URL}" \
    digest="${IMAGE_DIGEST}"

O formato preferido para o nome da imagem é image-URL:build-tag.

Se você criar imagens Docker, use a interface save_artifact para enviar essas imagens para as tarefas padrão de assinatura de imagem integrada e de varredura do dispositivo virtual CR IBM Informix.

Liberar

Ao término do pipeline, os artefatos construídos devem ser incluídos no inventário, para que possam ser promovidos para a implementação. O estágio release oferece flexibilidade para a inclusão de outros artefatos no inventário, como gráficos Helm.

Neste estágio, é possível usar o comando cocoa inventory add da CLI e os dados dos comandos de pipelinectl para criar as entradas de inventário.

Se houver problemas na execução de pipeline, você poderá optar por ignorar uma atualização de inventário para evitar um inventário problemático Para ignorar a atualização de inventário, use as seguintes variáveis de ambiente:

  • skip-inventory-update-on-failure Variável de ambiente de opção por participar do pipeline para especificar se o inventário será atualizado.
  • one-pipeline-status Configure como 1, se houver uma falha de estágio na execução de pipeline

Verifique essas variáveis antes de chamar cocoa inventory add neste estágio..

Exemplo

# Check the status of pipeline and then release the artifacts to inventory

ONE_PIPELINE_STATUS=$(get_env one-pipeline-status 0)
if [ -n "$(get_env skip-inventory-update-on-failure "")" ]; then
    if [ $ONE_PIPELINE_STATUS -eq 1 ]; then
          echo "Skipping release stage as some of the pipeline stages are not successful."
          exit 1
    fi
fi

#
# `list_artifacts` returns the list of the reference names of saved artifacts
#
list_artifacts | while IFS= read -r artifact ; do
    #
    # Add a new value to the inventory repository. `cocoa inventory add` creates a new file with the name option,
    # if does not exist otherwise overwrites it.
    #
    cocoa inventory add \
        --name="${artifact}" \
        --artifact="$(load_artifact $artifact name)" \
        --repository-url="$(load_repo app-repo url)" \
        --commit-sha="$(load_repo app-repo commit)" \
        --build-number="${BUILD_NUMBER}" \
        --pipeline-run-id="${PIPELINE_RUN_ID}" \
        --version="$(get_env version)" \
        --app-artifacts="{ \
            \"signature\": \"$(load_artifact $artifact signature)\", \
            \"provenance\": \"$(load_artifact $artifact name)\"\
        }"
done

Para usar a CLI, você deve instalá-la em seus scripts ou usar uma imagem de base que tenha a CLI pré-instalada.