Testergebnisse hinzufügen und Scripts zur Pipeline erstellen

Verbinden Sie Ihren bestehenden Test- und Build-Flow mit der Continuous Integration-Pipeline, indem Sie die Ergebnisse Ihrer neuen oder bestehenden Test- und Build-Skripte in den Continuous Integration-Flow der DevSecOps-Pipeline einfügen.

Beim Start der Pipeline klonen die Skripte von DevSecOps automatisch die Anwendungs- und Konfigurations-Repositories in die folgenden Verzeichnisse:

  1. Das Anwendungs-Repository wird geklont unter dem Pfad /workspace/app/<APP_REPO_NAME>

  2. Das Repository für die Pipeline-Konfiguration wird unter dem folgenden Pfad geklont /workspace/app/one-pipeline-config-repo

Wenn Sie zu irgendeinem Zeitpunkt Skripte aus diesen Repositories ausführen möchten, müssen Sie zunächst zu den entsprechenden Verzeichnissen navigieren. Sie können dazu eine der folgenden Methoden verwenden:

  1. Direktes Verwenden der geklonten Repository-Pfade
  • App-Repository: cd "${WORKSPACE}/$APP_REPO_NAME"

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

  1. Verwendung des Befehls load_repo
  • App-Repository: cd "${WORKSPACE}/$(load_repo app-repo path)"

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

$WORKSPACE bezieht sich auf den Wurzelpfad /workspace/app.

Sie können die folgenden Stages in der Pipeline für kontinuierliche Integration verwenden, um Test- und Buildschritte hinzuzufügen:

  • Einrichtung
  • Testen
  • Containerisieren (Build)
  • Freigeben

Einrichtung der Pipeline

Verwenden Sie die Setup-Phase, um Ihre Test- und Build-Umgebung einzurichten und Informationen in die Pipeline zu ziehen. Sie können z. B. mehrere App-bezogene Repositorys in einem einzigen Build verwenden. Sie können alle Repos klonen, die Sie benötigen, und die Pipeline bei Prüfungen und Scans im Zusammenhang mit der Einhaltung von Vorschriften auf diese Repos aufmerksam machen.

Das Standard-Anwendungs-Repository, das von der Pipeline intern geklont und der Pipeline über die Schnittstelle save_repo pipelinectl mit dem Referenznamen app-repo hinzugefügt wird. Wenn Sie die Pipeline anhand der Toolchain-Vorlage einrichten, wird das Standardrepository entweder über den Repositoryparameter der Pipeline-Benutzerschnittstelle (UI) bereitgestellt oder über den Namen seiner Toolchain-Bindung ausgewählt.

Wenn Sie weitere Repos verwenden möchten, klonen Sie diese in der Setup-Phase und fügen Sie sie über die gleiche Schnittstelle save_repo zur Pipeline hinzu.

Beispiel

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

Auf diese Weise kann der Rest der Pipeline diese Repositorys auf Compliance-Verstöße und Sicherheitslücken scannen.

Pfade, die unter Verwendung von save_repo gespeichert werden, müssen relativ zum Arbeitsbereichspfad sein.

Sie müssen das Tool pipelinectl nicht für Ihre Scripts oder Basisimages installieren; die Referenzpipeline stellt die Binärdateien für den Kontext Ihres Scripts bereit.

Testen

In dieser Stage führen Sie die Tests für Ihre Code-Repositorys aus. Sie können auf Ihre in der Einrichtungsphase hinzugefügten Repos über die Schnittstellen list_repos und load_repo pipelinectl zugreifen.

Beispiel

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

Die Kontrolle der Einhaltung der Einheitsprüfung basiert auf dem Exit-Code des Stufenskripts. Wenn Ihre Tests erfolgreich sind, beenden Sie mit 0. Ist dies nicht der Fall, wird am Ende ein Exit-Code ungleich null zurückgegeben.

Ergebnisse speichern

Ihre Tests erzeugen möglicherweise einige Berichtsartefakte, wie z. B. Testergebnisse in JSON oder XML. Verwenden Sie in dieser Phase die Schnittstelle save_result pipelinectl, um die Tests als Angabenartefakte an die erstellten Konformitätsangaben anzuhängen.

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

Der erste Parameter von 'save_results' muss der Name der DevSecOps-Pipeline aus der Konfigurationsstage sein, wie z. B. 'test', 'scan-artifact' oder 'acceptance-test'. Andernfalls kann der Spurensammler sie nicht finden und sie dem richtigen Beweisstück zuordnen.

Die Verwendung der Schnittstelle save_result pipelinectl stellt sicher, dass die Pipeline Ihre Ergebnis-Artefakte findet, sie in den Evidence Locker hochlädt und an den von der Pipeline erstellten Compliance-Nachweis anhängt.

Beispielnachweis, der für die Komponententests bei der Verwendung von save_result erstellt wird:

{
  "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"
    }
  ]
}

Build oder Containerisierung

In dieser Phase können Sie Ihre Artefakte bauen. Die Pipeline bietet einige Standardfunktionen für Artefakte vom Typ Docker-Image, aber Sie können hier beliebige Artefakte erstellen. Speichern Sie die erstellten Artefakte für die Pipeline, damit sie später Scans für sie ausführen oder die Artefakte in Ihrer Releasephase verwenden kann.

Wenn Sie Informationen zu Ihren erstellten Artefakten bereitstellen möchten, verwenden Sie die pipelinectl-Schnittstelle save_artifact.

Beispiel

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

Das bevorzugte Format für den Bildnamen ist image-URL:build-tag.

Wenn Sie Docker Images erstellen, verwenden Sie die Schnittstelle save_artifact, um diese Images für die standardmäßig integrierte Image-Signierung und CR IBM Informix Virtual Appliance-Scan-Aufgaben zu senden.

Freigeben

Am Ende der Pipeline müssen die erstellten Artefakte zum Bestand hinzugefügt werden, sodass sie zur Bereitstellung umgestuft werden können. Die Release-Stage bietet Flexibilität, wenn Sie weitere Artefakte, z. B. Helm-Charts, zum Bestand hinzufügen möchten.

In dieser Stage können Sie den CLI-Befehl cocoa inventory add und die Daten aus den pipelinectl-Befehlen verwenden, um die Bestandseinträge zu erstellen.

Wenn bei der Pipelineausführung Probleme auftreten, können Sie eine Bestandsaktualisierung überspringen, um einen problematischen Bestand zu vermeiden. Verwenden Sie die folgenden Umgebungsvariablen, um die Bestandsaktualisierung zu überspringen:

  • skip-inventory-update-on-failure Opt-in-Umgebungsvariable aus Pipeline, um anzugeben, ob der Bestand aktualisiert wird.
  • one-pipeline-status Auf 1 gesetzt, wenn ein Phasenfehler in der Pipelineausführung auftritt.

Überprüfen Sie diese Variablen, bevor Sie in dieser Phase cocoa inventory add aufrufen.

Beispiel

# 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

Um die Befehlszeilenschnittstelle zu verwenden, müssen Sie sie in Ihren Skripten installieren oder ein Basis-Image verwenden, auf dem die Befehlszeilenschnittstelle vorinstalliert ist.