Aggiungere i risultati del test e creare script alla pipeline

Collegare il flusso di test e build esistente alla pipeline di integrazione continua, aggiungendo i risultati degli script di test e build nuovi o esistenti al flusso di integrazione continua della pipeline DevSecOps.

All'inizio della pipeline, gli script DevSecOps clonano automaticamente i repository dell'applicazione e della configurazione nelle seguenti directory:

  1. Il repository dell'applicazione viene clonato nel percorso /workspace/app/<APP_REPO_NAME>

  2. Il repository di configurazione della pipeline viene clonato al percorso /workspace/app/one-pipeline-config-repo

In qualsiasi momento, se si desidera eseguire gli script che si trovano in questi repository, bisogna prima navigare nelle directory appropriate. È possibile farlo utilizzando uno dei seguenti metodi:

  1. Utilizzare direttamente i percorsi dei repository clonati
  • App repository: cd "${WORKSPACE}/$APP_REPO_NAME"

  • Repository di configurazione: cd "${WORKSPACE}/one-pipeline-config-repo/"

  1. Usare il comando load_repo
  • App repository: cd "${WORKSPACE}/$(load_repo app-repo path)"

  • Repository di configurazione: cd "${WORKSPACE}/$(load_repo one-pipeline-config-repo path)"

$WORKSPACE si riferisce al percorso principale /workspace/app.

È possibile utilizzare le seguenti fasi all'interno della pipeline di integrazione continua per aggiungere passi di test e build:

  • Configurazione
  • Verifica
  • Containerizza (build)
  • Rilascia

Configurazione pipeline

Utilizza la fase Configurazione per configurare il tuo ambiente di test e di build e inserire le informazioni nella pipeline. Ad esempio, puoi utilizzare più repository correlati all'applicazione in una sola build. Puoi clonare tutti i repository di cui hai bisogno e rendere la pipeline consapevole di tali repository in verifiche e scansioni relative alla conformità.

Il repository dell'applicazione predefinito clonato internamente dalla pipeline e aggiunto alla pipeline utilizzando l'interfaccia save_repo pipelinectl con il nome di riferimento app-repo. Il repository predefinito è fornito dal parametro dell'IU della pipeline del repository o selezionato dal suo nome di bind della toolchain, se configuri la pipeline dal template della toolchain.

Se vuoi utilizzare più repository, clonali nella fase di configurazione e utilizza la stessa interfaccia save_repo per aggiungerli alla pipeline.

Esempio

#
# 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}"

In questo modo il resto della pipeline può eseguire la scansione di questi repository alla ricerca di violazioni di conformità e vulnerabilità.

I percorsi salvati utilizzando save_repo devono essere relativi al percorso del workspace.

Non è necessario installare lo strumento pipelinectl per gli script o le immagini di base, la pipeline di riferimento fornisce i file binari per il contesto dello script.

Verifica

Questa fase è il punto in cui esegui i test sui tuoi repository di codice. Puoi accedere ai tuoi repository aggiunti nella fase di configurazione utilizzando le interfacce list_repos e load_repo pipelinectl.

Esempio

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

Il controllo di conformità del test unità si basa sul codice di uscita dello script dello stage. Se i test hanno esito positivo, uscire con 0. In caso contrario, restituire un codice di uscita diverso da zero alla fine.

Salvataggio dei risultati

I test potrebbero generare alcune risorse utente di report, ad esempio i risultati di un test in JSON o XML. Utilizzare l'interfaccia save_result pipelinectl in questa fase per collegare i test alla prova di conformità creata come risorse utente della prova.

#
# 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

Il primo parametro di save_results deve essere il nome della fase di configurazione della pipeline DevSecOps, come test, scan-artifact o acceptance-test. In caso contrario, il raccoglitore di prove non sarà in grado di trovarlo e collegarlo alla prova appropriata.

L'utilizzo dell'interfaccia pipelinectl save_result garantisce che la pipeline trovi le risorse utente dei risultati, che vengano caricate nel blocco delle prove e che siano collegate alla prova di conformità creata dalla pipeline.

Prova di esempio creata per i test di unità durante l'utilizzo di 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"
    }
  ]
}

Crea o containerizza

In questa fase, è possibile creare le risorse utente. La pipeline fornisce alcune funzioni predefinite per le risorse utente di tipo immagine docker, ma qui puoi creare qualsiasi risorsa utente. Salva le risorse utente create per la pipeline, in modo che successivamente possa eseguire le scansioni su di essa o utilizzare le risorse utente nella tua fase di release.

Per fornire informazioni sulle tue risorse utente create, utilizza l'interfaccia pipelinectl save_artifact.

Esempio

#
# 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}"

Il formato preferito per il nome dell'immagine è image-URL:build-tag.

Se crei immagini Docker, utilizza l'interfaccia save_artifact per inviare tali immagini per la firma dell'immagine integrata predefinita e le attività di scansione di IBM Informix Virtual Appliance.

Rilascia

Alla fine della pipeline, le risorse utente create devono essere aggiunte all'inventario, in modo che possano essere promosse alla distribuzione. La fase di release fornisce flessibilità se vuoi aggiungere altre risorse utente all'inventario, come i grafici Helm.

In questa fase, puoi utilizzare il comando cocoa inventory add della CLI e i dati dei comandi pipelinectl per creare le voci di inventario.

Se si verificano dei problemi durante l'esecuzione della pipeline, è possibile scegliere di ignorare un aggiornamento dell'inventario per evitare un inventario problematico. Per ignorare l'aggiornamento dell'inventario, utilizzare le seguenti variabili di ambiente:

  • skip-inventory-update-on-failure Variabile di ambiente opt - in dalla pipeline per specificare se l'inventario è aggiornato.
  • one-pipeline-status Imposta su 1, se si verifica un errore di fase nell'esecuzione della pipeline.

Controllare queste variabili prima di chiamare cocoa inventory add in questo stage.

Esempio

# 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

Per utilizzare la CLI, è necessario installarla nei propri script o utilizzare un'immagine di base su cui è preinstallata la CLI.