diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..e3aa4dab --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,58 @@ +# Copyright 2024 Defense Unicorns +# SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial + +include: + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/commitlint@$CI_COMMIT_SHA + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/lint@$CI_COMMIT_SHA + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/test@$CI_COMMIT_SHA + inputs: + # if you have additional report artifacts to add to the gitlab + # artifact zip file you can add the path here and the entire directory + # will be included + #reports-path: sample-reports/playwright + runs-on: gitlab-runner-4c-${ARCH} + flavor: $FLAVOR + type: $TYPE + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/publish@$CI_COMMIT_SHA + inputs: + runs-on: gitlab-runner-4c-${ARCH} + flavor: $FLAVOR + # if you have additional report artifacts to add to the gitlab + # artifact zip file you can add the path here and the entire directory + # will be included + #reports-path: sample-reports/playwright + + # if setting target repo, this will be used directly for the oci publish + #target-repo: ${CI_REGISTRY}/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME} + + # if you override team here it will be included in the determined target repo + # for the oci publish (default is uds) + # only used if target-repo is not set + #team: my-team + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/scorecard@$CI_COMMIT_SHA + +test: + artifacts: + # if you have specific report types that are natively supported by + # gitlab you can include those here and they'll be included in addition to the + # artifact containing debug logs, oscal, etc. + # (e.g. Junit tests, sast reports, etc) + # see: https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html + # reports: + # junit: sample-reports/junit.xml + parallel: + matrix: + - FLAVOR: [upstream, unicorn] + ARCH: [amd64, arm64] + TYPE: [install, upgrade] + - FLAVOR: [registry1] + ARCH: [amd64] + TYPE: [install, upgrade] + +publish: + parallel: + matrix: + - FLAVOR: [upstream, unicorn] + ARCH: [amd64, arm64] + - FLAVOR: [registry1] + ARCH: [amd64] diff --git a/release-please-config.json b/release-please-config.json index c11d8ecc..18840e1e 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -12,6 +12,7 @@ "versioning": "default", "extra-files": [ "bundle/uds-bundle.yaml", + "releaser.yaml", "tasks.yaml", "zarf.yaml" ] diff --git a/releaser.yaml b/releaser.yaml new file mode 100644 index 00000000..7b1f550d --- /dev/null +++ b/releaser.yaml @@ -0,0 +1,16 @@ +# Copyright 2024 Defense Unicorns +# SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial + +flavors: + - name: upstream + # x-release-please-start-version + version: 1.1.2 + # x-release-please-end + - name: registry1 + # x-release-please-start-version + version: 1.1.2 + # x-release-please-end + - name: unicorn + # x-release-please-start-version + version: 1.1.2 + # x-release-please-end diff --git a/tasks.yaml b/tasks.yaml index 077b58ef..185827e1 100644 --- a/tasks.yaml +++ b/tasks.yaml @@ -13,6 +13,12 @@ includes: - badge: ./tasks/badge.yaml - actions: ./tasks/actions.yaml +variables: + - name: VERSION + # x-release-please-start-version + default: 1.1.2 + # x-release-please-end + tasks: - name: default description: Create and deploy the nginx package on a fresh cluster @@ -150,6 +156,4 @@ tasks: - description: Publish the packages task: publish:package with: - # x-release-please-start-version - version: 1.1.2 - # x-release-please-end + version: ${VERSION} diff --git a/tasks/README.md b/tasks/README.md index 575af589..58fc5384 100644 --- a/tasks/README.md +++ b/tasks/README.md @@ -110,10 +110,13 @@ There are multiple task files available in this repository with different object | Name | Description | |------|-------------| +| **authenticate-registries** | Log in to the registries for testing and publishing UDS Packages | | **debug-output** | Print debug output from a k8s cluster | | **clean-gh-runner** | Cleanup unneeded files to free space on a GitHub runner | +| **install-deps** | Install the runner dependencies for testing UDS Packages | | **save-logs** | Save Pod and Node logs from a cluster and fix permissions | | **setup-environment** | Setup the runner environment for testing UDS Packages | | **test-deploy** | Test a deployment of a UDS package/bundle | | **verify-badge** | Perform verification to assist with UDS badge certification | | **determine-arch** | Determine the architecture of the current machine | +| **registry-login** | Log in to an OCI registry | diff --git a/tasks/actions.yaml b/tasks/actions.yaml index 032e7db9..34491b79 100644 --- a/tasks/actions.yaml +++ b/tasks/actions.yaml @@ -8,8 +8,16 @@ variables: default: "" - name: GH_TOKEN default: "" + - name: GITLAB_REGISTRY_USER + default: "" + - name: GITLAB_REGISTRY_URL + default: "" + - name: GITLAB_REGISTRY_TOKEN + default: "" - name: CHAINGUARD_IDENTITY default: "" + - name: CHAINGUARD_TOKEN + default: "" - name: CHART_PATH default: chart/ - name: GROUP_NAME @@ -22,6 +30,8 @@ variables: default: "" - name: OPTIONS default: "" + - name: LOG_DIR + default: /tmp - name: GO_VERSION default: 1.23.1 @@ -32,19 +42,19 @@ tasks: - description: Print basic debug info for a k8s cluster cmd: | echo "::group::kubectl get all" - uds zarf tools kubectl get all -A || echo "failed" | tee /tmp/debug-k-get-all.log + uds zarf tools kubectl get all -A || echo "failed" | tee ${{ .variables.LOG_DIR }}/debug-k-get-all.log echo "::endgroup::" echo "::group::kubectl get pv,pvc" - uds zarf tools kubectl get pv,pvc -A || echo "failed" | tee /tmp/debug-k-get-pv-pvc.log + uds zarf tools kubectl get pv,pvc -A || echo "failed" | tee ${{ .variables.LOG_DIR }}/debug-k-get-pv-pvc.log echo "::endgroup::" echo "::group::kubectl get package" - uds zarf tools kubectl get package -A || echo "failed" | tee /tmp/debug-k-get-package.log + uds zarf tools kubectl get package -A || echo "failed" | tee ${{ .variables.LOG_DIR }}/debug-k-get-package.log echo "::endgroup::" echo "::group::kubectl get events" - uds zarf tools kubectl get events -A --sort-by='.lastTimestamp' || echo "failed" | tee /tmp/debug-k-get-events.log + uds zarf tools kubectl get events -A --sort-by='.lastTimestamp' || echo "failed" | tee ${{ .variables.LOG_DIR }}/debug-k-get-events.log echo "::endgroup::" echo "::group::kubectl describe nodes" - uds zarf tools kubectl describe nodes k3d-uds-server-0 || echo "failed" | tee /tmp/debug-k-describe-node.log + uds zarf tools kubectl describe nodes k3d-uds-server-0 || echo "failed" | tee ${{ .variables.LOG_DIR }}/debug-k-describe-node.log echo "::endgroup::" - name: clean-gh-runner @@ -70,7 +80,7 @@ tasks: CONTAINER_NAME="k3d-uds-server-0" if docker ps | grep -q "$CONTAINER_NAME"; then echo "Container $CONTAINER_NAME is running. Proceeding with log copy..." - docker cp "${CONTAINER_NAME}:/var/log/" /tmp/uds-containerd-logs + docker cp "${CONTAINER_NAME}:/var/log/" ${{ .variables.LOG_DIR }}/uds-containerd-logs else echo "Container $CONTAINER_NAME is not running. Skipping log copy." fi @@ -78,16 +88,24 @@ tasks: - description: Dump Node Logs cmd: | docker ps --filter "name=k3d" --format "{{.Names}}" | while read -r line; do - docker logs "$line" 2> "/tmp/$line.log" + docker logs "$line" 2> "${{ .variables.LOG_DIR }}/$line.log" done - description: Fix log permissions cmd: | - sudo chown "$USER" /tmp/zarf-*.log || echo "" - sudo chown "$USER" /tmp/uds-*.log || echo "" + sudo chown "$USER" ${{ .variables.LOG_DIR }}/zarf-*.log || echo "" + sudo chown "$USER" ${{ .variables.LOG_DIR }}/uds-*.log || echo "" - name: setup-environment description: Setup the runner environment for testing UDS Packages + actions: + - description: Install dependencies + task: install-deps + - description: authenticate to the registries + task: authenticate-registries + + - name: install-deps + description: Install the runner dependencies for testing UDS Packages actions: - description: Install k3d env: @@ -107,33 +125,58 @@ tasks: "https://github.com/defenseunicorns/lula/releases/download/${LULA_VERSION}/lula_${LULA_VERSION}_$(uname -s)_${{ .variables.ARCH }}" \ && chmod +x /usr/local/bin/lula + - name: authenticate-registries + description: Log in to the registries for testing and publishing UDS Packages + actions: - description: Iron Bank Login if: ${{ ne .variables.REGISTRY1_USERNAME "" }} - cmd: | - echo "${{ .variables.REGISTRY1_PASSWORD }}" | ./uds zarf tools registry login -u "${{ .variables.REGISTRY1_USERNAME }}" --password-stdin registry1.dso.mil + task: registry-login + with: + registry: registry1.dso.mil + registry_username: ${{ .variables.REGISTRY1_USERNAME }} + registry_token: ${{ .variables.REGISTRY1_PASSWORD }} - description: Chainguard Login if: ${{ ne .variables.CHAINGUARD_IDENTITY "" }} cmd: | - curl -o /usr/local/bin/chainctl -L \ - "https://dl.enforce.dev/chainctl/latest/chainctl_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/aarch64/arm64/')" \ - && chmod +x /usr/local/bin/chainctl + if [ -z "$GITLAB_CI" ]; then + curl -o /usr/local/bin/chainctl -L \ + "https://dl.enforce.dev/chainctl/latest/chainctl_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/aarch64/arm64/')" \ + && chmod +x /usr/local/bin/chainctl + fi + + LOGIN_ARGS="--identity \"${{ .variables.CHAINGUARD_IDENTITY }}\"" + TOKEN=${{ .variables.CHAINGUARD_TOKEN }} + if [ -n "$TOKEN" ]; then + LOGIN_ARGS="$LOGIN_ARGS --identity-token \"$TOKEN\"" + fi - if chainctl auth login --identity "${{ .variables.CHAINGUARD_IDENTITY }}" -v=0; then + if eval chainctl auth login "$LOGIN_ARGS" -v=0; then echo Logged in as ${{ .variables.CHAINGUARD_IDENTITY }}! else echo Unable to assume the identity ${{ .variables.CHAINGUARD_IDENTITY }}. exit 1 fi - if ! chainctl auth configure-docker --identity "${{ .variables.CHAINGUARD_IDENTITY }}" -v=0; then + if ! eval chainctl auth configure-docker "$LOGIN_ARGS" -v=0; then echo Unable to register credential helper as ${{ .variables.CHAINGUARD_IDENTITY }}. exit 1 fi - - description: GHCR Login + - description: GHCR Registry Login if: ${{ ne .variables.GH_TOKEN "" }} - cmd: | - echo "${{ .variables.GH_TOKEN }}" | uds zarf tools registry login -u "dummy" --password-stdin ghcr.io + task: registry-login + with: + registry: ghcr.io + registry_username: dummy + registry_token: ${{ .variables.GH_TOKEN }} + + - description: Gitlab Registry Login + if: ${{ ne .variables.GITLAB_REGISTRY_USER "" }} + task: registry-login + with: + registry: ${{ .variables.GITLAB_REGISTRY_URL }} + registry_username: ${{ .variables.GITLAB_REGISTRY_USER }} + registry_token: ${{ .variables.GITLAB_REGISTRY_TOKEN }} - description: Package Specific CI Setup cmd: | @@ -179,7 +222,7 @@ tasks: --set GROUP_NAME="${{ .variables.GROUP_NAME }}" \ --set COMMON_ZARF="${{ .variables.COMMON_ZARF }}" - # Common task + # Common tasks - name: determine-arch description: Determine the architecture of the current machine actions: @@ -191,3 +234,22 @@ tasks: darwin: bash setVariables: - name: ARCH + + - name: registry-login + description: Log in to an OCI registry + inputs: + registry: + description: The registry to log in to + required: true + registry_username: + description: The username to log in with + required: true + default: replace-me + registry_token: + description: The token to log in with + required: true + actions: + - description: Registry Login + cmd: | + set -x + echo "${{ .inputs.registry_token }}" | ./uds zarf tools registry login -u "${{ .inputs.registry_username }}" --password-stdin "${{ .inputs.registry }}" diff --git a/tasks/lint.yaml b/tasks/lint.yaml index c2369edf..6426df87 100644 --- a/tasks/lint.yaml +++ b/tasks/lint.yaml @@ -112,6 +112,7 @@ tasks: fi } + shopt -s nullglob # if nothing matches the glob expand to nothing # Lint all scripts in Maru tasks for yaml_file in tasks.yaml tasks/*.yaml; do @@ -129,11 +130,13 @@ tasks: lint_scripts "$yaml_file" "$raw_scripts" fi done + shopt -u nullglob #reset nullglob behavior # Lint all .sh files in the current directory echo "Processing .sh files..." find . -type f -name "*.sh" -exec shellcheck {} + + shopt -s nullglob # if nothing matches the glob expand to nothing # Lint all scripts in GitHub workflows for yaml_file in .github/workflows/*.yaml; do @@ -151,6 +154,7 @@ tasks: lint_scripts "$yaml_file" "$raw_scripts" fi done + shopt -u nullglob #reset nullglob behavior - name: license description: Lint for the SPDX license identifier being in source files diff --git a/tasks/publish.yaml b/tasks/publish.yaml index e4f5185d..87d732f5 100644 --- a/tasks/publish.yaml +++ b/tasks/publish.yaml @@ -7,6 +7,8 @@ includes: variables: - name: FLAVOR default: upstream + - name: TEAM + default: uds tasks: - name: package @@ -30,7 +32,7 @@ tasks: actions: - task: utils:determine-repo with: - team: ${{.inputs.team}} + team: ${{.variables.TEAM}} - description: Get the current Zarf package name cmd: cat ${{ .inputs.path }}/zarf.yaml | ./uds zarf tools yq .metadata.name setVariables: diff --git a/tasks/setup.yaml b/tasks/setup.yaml index bf90f012..2c96869e 100644 --- a/tasks/setup.yaml +++ b/tasks/setup.yaml @@ -52,7 +52,7 @@ tasks: - name: create-doug-user description: Creates a user named 'doug' in the uds realm of keycloak (using the default admin account) actions: - - description: Creating the 'doug' user int he 'uds' realm + - description: Creating the 'doug' user in the 'uds' realm cmd: | KEYCLOAK_ADMIN_PASSWORD=$(./uds zarf tools kubectl get secret -n keycloak keycloak-admin-password -o jsonpath='{.data.password}' | base64 -d) KEYCLOAK_ADMIN_TOKEN=$(curl -s --location "https://keycloak.admin.uds.dev/realms/master/protocol/openid-connect/token" \ diff --git a/tasks/utils.yaml b/tasks/utils.yaml index 133dfb64..ff9caf11 100644 --- a/tasks/utils.yaml +++ b/tasks/utils.yaml @@ -4,6 +4,7 @@ variables: - name: FLAVOR default: upstream + - name: TARGET_REPO tasks: - name: determine-repo @@ -22,7 +23,12 @@ tasks: description: Whether this is a snapshot release default: "false" actions: + - description: Use existing TARGET_REPO value from variable + # if the caller explicitly set a value for TARGET_REPO we'll use it + if: ${{ ne .variables.TARGET_REPO "" }} + cmd: echo "Using supplied value TARGET_REPO=${TARGET_REPO}" - description: Determine repository for the given flavor/type of release + if: ${{ eq .variables.TARGET_REPO "" }} cmd: | repo="${{.inputs.base_repo}}" # unicorn flavor = private repository diff --git a/templates/README.md b/templates/README.md new file mode 100644 index 00000000..a8b9fea4 --- /dev/null +++ b/templates/README.md @@ -0,0 +1,53 @@ +# UDS Common GitLab CI Components + +This folder contains the GitLab CI Components for UDS Common, analogous to the GitHub callable workflows under the `./github/workflows` directory. The included components are as follows: + +1. Lint +1. Commitlint +1. Test +1. Publish +1. Scorecard + +The .gitlab-ci.yml at the root of this repo serves as an example and test of how to call these components. That being said, a general example of how to include these components in a GitLab `uds-package` is as follows: + +```yaml +include: + # include the component from a published tag of uds-common + - component: $CI_SERVER_FQDN/path/to/uds-common/commitlint@0.0.0 + - component: $CI_SERVER_FQDN/path/to/uds-common/lint@0.0.0 + - component: $CI_SERVER_FQDN/path/to/uds-common/test@0.0.0 + inputs: + flavor: $FLAVOR + type: $TYPE + runsOn: gitlab-runner-4c-${ARCH} + - component: $CI_SERVER_FQDN/path/to/uds-common/publish@0.0.0 + inputs: + flavor: $FLAVOR + runsOn: gitlab-runner-4c-${ARCH} +# Define a matrix for the test job to follow for the flavors that exist for your package +test: + parallel: + matrix: + - FLAVOR: [upstream, unicorn] + ARCH: [amd64, arm64] + TYPE: [install, upgrade] + - FLAVOR: [registry1] + ARCH: [amd64] + TYPE: [install, upgrade] + +# Define matrix for publish job of flavors and architectures +publish: + parallel: + matrix: + - FLAVOR: [upstream, unicorn] + ARCH: [amd64, arm64] + - FLAVOR: [registry1] + ARCH: [amd64] +``` + +## Repo Setup + +Setting up your gitlab repo to work properly with these components will require a few steps: + +1. Enable a Protected Branch and set approval rules +2. Create a GitLab Token for the Scorecard Component to run and store in project variables. diff --git a/templates/commitlint.yml b/templates/commitlint.yml new file mode 100644 index 00000000..11b0e711 --- /dev/null +++ b/templates/commitlint.yml @@ -0,0 +1,19 @@ +# Copyright 2024 Defense Unicorns +# SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial + +spec: + inputs: + runs-on: + default: gitlab-runner-4c-amd64 +--- +commitlint: + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + script: + - npm install --save-dev @commitlint/config-conventional@19.5.0 + - npm install --save-dev @commitlint/cli@19.5.0 + - | + echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js + - echo "$CI_MERGE_REQUEST_TITLE" | npx commitlint + tags: + - $[[ inputs.runs-on ]] diff --git a/templates/lint.yml b/templates/lint.yml new file mode 100644 index 00000000..f37a769c --- /dev/null +++ b/templates/lint.yml @@ -0,0 +1,22 @@ +# Copyright 2024 Defense Unicorns +# SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial + +spec: + inputs: + runs-on: + default: gitlab-runner-4c-amd64 +--- +lint: + rules: + - if: $CI_MERGE_REQUEST_ID + script: + # this is needed for yamllint to be on path + - export PATH=/home/ubuntu/.local/bin:$PATH + + # Install lint dependencies + - uds run lint:deps --no-progress + + # Lint the repository + - uds run lint:all --no-progress + tags: + - $[[ inputs.runs-on ]] diff --git a/templates/publish.yml b/templates/publish.yml new file mode 100644 index 00000000..c7ebdb4f --- /dev/null +++ b/templates/publish.yml @@ -0,0 +1,110 @@ +# Copyright 2024 Defense Unicorns +# SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial + +spec: + inputs: + runs-on: + flavor: + artifact-dir: + default: .ci_artifacts + reports-path: + default: "" + registry1-username: + default: ${IRON_BANK_ROBOT_USERNAME} + registry1-password: + default: ${IRON_BANK_ROBOT_PASSWORD} + chainguard-identity: + default: ${CHAINGUARD_IDENTITY} + target-repo: + default: "" + team: + default: uds +--- +publish: + variables: + GIT_STRATEGY: clone + GIT_DEPTH: 0 + id_tokens: + CHAINGUARD_TOKEN: + aud: https://console-api.enforce.dev + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + - if: $CI_MERGE_REQUEST_ID + variables: # Override DRY_RUN defined + DRY_RUN: "true" # at the job level. + script: + # Dry run on non-tag runs + - OPTIONS="--no-progress" + - if [[ "$DRY_RUN" == "true" ]]; then OPTIONS="$OPTIONS --dry-run"; fi + + # Environment setup + - | + uds run actions:authenticate-registries --set REGISTRY1_USERNAME="$[[ inputs.registry1-username ]]" \ + --set REGISTRY1_PASSWORD="$[[ inputs.registry1-password ]]" \ + --set CHAINGUARD_IDENTITY="$[[ inputs.chainguard-identity ]]" \ + --set CHAINGUARD_TOKEN="$CHAINGUARD_TOKEN" \ + --set GITLAB_REGISTRY_URL="$CI_REGISTRY" \ + --set GITLAB_REGISTRY_USER="$CI_REGISTRY_USER" \ + --set GITLAB_REGISTRY_TOKEN="$CI_REGISTRY_PASSWORD" + + # Check if release is necessary for flavor and exit early if not + - | + if ! uds-releaser check "${FLAVOR}"; then + echo "No release necessary" + [[ "$DRY_RUN" != "true" ]] && exit 0 + fi + + # Modify zarf package and uds bundle to have the correct version + - uds-releaser update-yaml ${FLAVOR} + + # Publish Package + - | + if uds run --list | grep -q 'publish-package'; then + TASK_NAME="publish-package" + else + TASK_NAME="publish-release" + fi + + ARGS="--set FLAVOR=\"$[[ inputs.flavor ]]\" \ + --set VERSION=\"$(uds-releaser show ${FLAVOR} --version-only)\"" + + if [[ -n "$[[ inputs.target-repo ]]" ]]; then + ARGS+=" --set TARGET_REPO=\"$[[ inputs.target-repo ]]\"" + else + ARGS+=" --set TEAM=\"$[[ inputs.team ]]\"" + fi + + uds run $TASK_NAME ${ARGS} ${OPTIONS} + + # Create tag and release + - | + if [[ "$DRY_RUN" == "true" ]]; then + echo "Dry run, skipping release" + else + uds-releaser release gitlab "${FLAVOR}" + fi + + after_script: + # Save logs, which will run even if the script section fails + - echo -e "\e[0Ksection_start:`date +%s`:afterscript_section[collapsed=true]\r\e[0KAfter Script Output" + - | + mkdir -p $[[ inputs.artifact-dir ]]/logs + uds run actions:debug-output --set LOG_DIR="$[[ inputs.artifact-dir ]]/logs" + uds run actions:save-logs --set LOG_DIR="$[[ inputs.artifact-dir ]]/logs" + # gitlab only supports one artifact unless you define a specific supported "report type" + # so in this generic case we will just add the reports to the included artifact dir + if [ -n "$[[ inputs.reports-path ]]" ]; then + cp -r "$[[ inputs.reports-path ]]" "$[[ inputs.artifact-dir ]]" + fi + - echo -e "\e[0Ksection_end:`date +%s`:afterscript_section\r\e[0K" + + artifacts: + when: always + name: artifacts-$[[ inputs.flavor ]]-${CI_PIPELINE_ID}-${CI_JOB_ID} + paths: + # Save debug logs as artifacts + - $[[ inputs.artifact-dir ]] + - oscal-assessment-results.yaml + + tags: + - $[[ inputs.runs-on ]] diff --git a/templates/scorecard.yml b/templates/scorecard.yml new file mode 100644 index 00000000..117e3d39 --- /dev/null +++ b/templates/scorecard.yml @@ -0,0 +1,40 @@ +# Copyright 2024 Defense Unicorns +# SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial + +spec: + inputs: + runs-on: + default: gitlab-runner-4c-amd64 +--- +run-scorecard: + #todo (ewyles) - decide correct time to run this. on github it runs on merge to main + rules: + - if: $CI_MERGE_REQUEST_ID + script: + - echo 'Running scorecard' + - docker run -e SCORECARD_EXPERIMENTAL=1 -e GITLAB_AUTH_TOKEN=$SCORECARD_TOKEN gcr.io/openssf/scorecard:stable --repo $CI_PROJECT_URL --format=json 1>openssf_scorecard.json + - echo -e "\e[0Ksection_start:`date +%s`:scorecard_section[collapsed=true]\r\e[0KScorecard JSON Output" + - cat openssf_scorecard.json | jq + - echo -e "\e[0Ksection_end:`date +%s`:scorecard_section\r\e[0K" + + # todo (ewyles) - decide if we want to block on a minimum score at some point. Right now it just logs a warning + - | + # Minimum allowed score value + min_score=1.0 + + # Extract the score using jq + score=$(jq '.score' openssf_scorecard.json) + + # Compare the score with the minimum allowed value + if (( $(echo "$score < $min_score" | bc -l) )); then + echo -e "\033[33mWARNING: The score ($score) is below the minimum allowed value ($min_score).\033[0m" + else + echo "The score ($score) meets or exceeds the minimum allowed value ($min_score)." + fi + artifacts: + when: always + name: openssf_scorecard.json + paths: + - openssf_scorecard.json + tags: + - $[[ inputs.runs-on ]] diff --git a/templates/test.yml b/templates/test.yml new file mode 100644 index 00000000..8d6a14ec --- /dev/null +++ b/templates/test.yml @@ -0,0 +1,89 @@ +# Copyright 2024 Defense Unicorns +# SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial + +spec: + inputs: + runs-on: + flavor: + type: + artifact-dir: + default: .ci_artifacts + reports-path: + default: "" + registry1-username: + default: ${IRON_BANK_ROBOT_USERNAME} + registry1-password: + default: ${IRON_BANK_ROBOT_PASSWORD} + chainguard-identity: + default: ${CHAINGUARD_IDENTITY} +--- +test: + id_tokens: + CHAINGUARD_TOKEN: + aud: https://console-api.enforce.dev + rules: + - if: $CI_MERGE_REQUEST_ID + when: always + allow_failure: + exit_codes: 222 # using something here to exit with a warning + script: + - | + # Check if any tag exists + TAG="$(git describe --tags "$(git rev-list --tags --max-count=1)" 2>/dev/null || echo '')" + + if [ -z "$TAG" ]; then + echo "No Git tags found. Skipping upgrade check." + else + # Checkout the repository at the latest tag + git checkout "$TAG" + + # Extract upgrade flavors and set UPGRADE_FLAVORS + UPGRADE_FLAVORS=$(cat zarf.yaml | yq '.components[] | select(.only | has("flavor")) | .only.flavor' | paste -s -d, -) + + # change back to the commit branch for the rest of the job + git checkout "$CI_COMMIT_BRANCH" + fi + + - | + if [[ "$[[ inputs.type ]]" == "upgrade" && "$UPGRADE_FLAVORS" != *"$[[ inputs.flavor ]]"* ]]; then + + # this is not ideal but gitlab rules are evaluated before any jobs run, so variables are not accessible in there + # at least this way we can exit with a warning + echo -e "\033[33mWARNING: Skipping the job as the '$[[ inputs.flavor ]]' flavor is not in upgrade flavors list '$UPGRADE_FLAVORS'\033[0m"; + + exit 222; #this signals gitlab to exit with a warning because of the value of allow_failure.exit_codes above. + fi + - touch job_not_skipped + - | + uds run actions:authenticate-registries --set REGISTRY1_USERNAME="$[[ inputs.registry1-username ]]" \ + --set REGISTRY1_PASSWORD="$[[ inputs.registry1-password ]]" \ + --set CHAINGUARD_IDENTITY="$[[ inputs.chainguard-identity ]]" \ + --set CHAINGUARD_TOKEN="$CHAINGUARD_TOKEN" \ + --set GITLAB_REGISTRY_URL="$CI_REGISTRY" \ + --set GITLAB_REGISTRY_USER="$CI_REGISTRY_USER" \ + --set GITLAB_REGISTRY_TOKEN="$CI_REGISTRY_PASSWORD" + - uds run actions:test-deploy --set FLAVOR="$[[ inputs.flavor ]]" --set TYPE="$[[ inputs.type ]]" + - uds run actions:verify-badge + + after_script: + - | + if [ -f job_not_skipped ]; then + mkdir -p $[[ inputs.artifact-dir ]]/logs + uds run actions:debug-output --set LOG_DIR="$[[ inputs.artifact-dir ]]/logs" + uds run actions:save-logs --set LOG_DIR="$[[ inputs.artifact-dir ]]/logs" + + # gitlab only supports one artifact unless you define a specific supported "report type" + # so in this generic case we will just add the reports to the included artifact dir + if [ -n "$[[ inputs.reports-path ]]" ]; then + cp -r "$[[ inputs.reports-path ]]" "$[[ inputs.artifact-dir ]]" + fi + fi + + artifacts: + when: always + name: artifacts-$[[ inputs.type ]]-$[[ inputs.flavor ]]-${CI_PIPELINE_ID}-${CI_JOB_ID} + paths: + - $[[ inputs.artifact-dir ]] + - oscal-assessment-results.yaml + tags: + - $[[ inputs.runs-on ]]