From ce8c45c8e0063d0a8c5bc767a33ed67aa71edfa0 Mon Sep 17 00:00:00 2001 From: Mike Houston <60653100+m-houston@users.noreply.github.com> Date: Mon, 10 Mar 2025 17:06:30 +0000 Subject: [PATCH 1/2] CCM-8881: Sync changes from repository template (#335) --- .github/actions/lint-terraform/action.yaml | 3 +- .github/actions/tfsec/action.yaml | 2 - .../scheduled-repository-template-sync.yaml | 2 +- .gitignore | 1 + .gitleaksignore | 2 + .tool-versions | 4 +- infrastructure/terraform/bin/terraform.sh | 57 ++++++------- .../config/.repository-template-sync-ignore | 8 +- .../config/.repository-template-sync-merge | 7 ++ scripts/config/gitleaks.toml | 14 +++- scripts/config/pre-commit.yaml | 77 +++++++++++------- scripts/config/sonar-scanner.properties | 1 + scripts/git-repo/auto-link.md | 11 +++ scripts/git-repo/auto-link.sh | 9 +++ scripts/git-repo/branch-protection.md | 11 +++ scripts/git-repo/branch-protection.sh | 48 +++++++++++ scripts/githooks/check-markdown-format.sh | 2 +- scripts/githooks/sort-dictionary.sh | 48 +++++++++++ scripts/githooks/sync-template-repo.sh | 57 ++++++++++--- scripts/maintenance/merge.js | 81 +++++++++++++++++++ 20 files changed, 367 insertions(+), 78 deletions(-) create mode 100644 scripts/config/.repository-template-sync-merge create mode 100644 scripts/git-repo/auto-link.md create mode 100644 scripts/git-repo/auto-link.sh create mode 100644 scripts/git-repo/branch-protection.md create mode 100755 scripts/git-repo/branch-protection.sh create mode 100755 scripts/githooks/sort-dictionary.sh create mode 100644 scripts/maintenance/merge.js diff --git a/.github/actions/lint-terraform/action.yaml b/.github/actions/lint-terraform/action.yaml index 7017b7de8..28d990cd7 100644 --- a/.github/actions/lint-terraform/action.yaml +++ b/.github/actions/lint-terraform/action.yaml @@ -7,8 +7,6 @@ inputs: runs: using: "composite" steps: - - uses: hashicorp/setup-terraform@v3 - - uses: asdf-vm/actions/setup@v3 - name: "Check Terraform format" shell: bash run: | @@ -18,5 +16,6 @@ runs: run: | stacks=${{ inputs.root-modules }} for dir in $(find infrastructure/environments -maxdepth 1 -mindepth 1 -type d; echo ${stacks//,/$'\n'}); do + dir=$dir opts='-backend=false' make terraform-init dir=$dir make terraform-validate done diff --git a/.github/actions/tfsec/action.yaml b/.github/actions/tfsec/action.yaml index 11140506b..ff5fec485 100644 --- a/.github/actions/tfsec/action.yaml +++ b/.github/actions/tfsec/action.yaml @@ -3,8 +3,6 @@ description: "Scan HCL using TFSec" runs: using: "composite" steps: - - uses: hashicorp/setup-terraform@v3 - - uses: asdf-vm/actions/setup@v3 - name: "TFSec Scan - Components" shell: bash run: | diff --git a/.github/workflows/scheduled-repository-template-sync.yaml b/.github/workflows/scheduled-repository-template-sync.yaml index 6755c83b4..a8284425a 100644 --- a/.github/workflows/scheduled-repository-template-sync.yaml +++ b/.github/workflows/scheduled-repository-template-sync.yaml @@ -27,7 +27,7 @@ jobs: - name: Run syncronisation script run: | - ./scripts/githooks/sync-template-repo.sh + ./nhs-notify-repository-template/scripts/githooks/sync-template-repo.sh rm -Rf ./nhs-notify-repository-template - name: Create Pull Request diff --git a/.gitignore b/.gitignore index af4725c7c..1aff5e1fd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *sbom*report*.json *vulnerabilities*report*.json *report*json.zip +version.json .version *.code-workspace diff --git a/.gitleaksignore b/.gitleaksignore index d94588148..151a53be7 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -3,3 +3,5 @@ cd9c0efec38c5d63053dd865e5d4e207c0760d91:docs/guides/Perform_static_analysis.md:generic-api-key:37 87312c6a627a7b0420956d49187fd15b130df170:src/__tests__/components/molecules/LoginStatus.test.tsx:jwt:23 37ca9f5670f4cd7d91869845ca27defbe6156bb9:src/__tests__/components/molecules/LoginStatus.test.tsx:jwt:23 +b19d88d1d92b0530f065feefcf25d8cdd82a876a:tests/test-team/auth/user.json:jwt:15 +b19d88d1d92b0530f065feefcf25d8cdd82a876a:tests/test-team/auth/user.json:jwt:25 diff --git a/.tool-versions b/.tool-versions index e6939c267..5f6bb2f9c 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,5 +1,5 @@ act 0.2.64 -gitleaks 8.18.4 +gitleaks 8.24.0 pre-commit 3.6.0 terraform 1.9.2 terraform-docs 0.19.0 @@ -13,7 +13,7 @@ nodejs 20.18.2 # TODO: Move this section - consider using a different file for the repository template dependencies. # docker/ghcr.io/anchore/grype v0.69.1@sha256:d41fcb371d0af59f311e72123dff46900ebd6d0482391b5a830853ee4f9d1a76 # SEE: https://github.com/anchore/grype/pkgs/container/grype # docker/ghcr.io/anchore/syft v0.92.0@sha256:63c60f0a21efb13e80aa1359ab243e49213b6cc2d7e0f8179da38e6913b997e0 # SEE: https://github.com/anchore/syft/pkgs/container/syft -# docker/ghcr.io/gitleaks/gitleaks v8.18.0@sha256:fd2b5cab12b563d2cc538b14631764a1c25577780e3b7dba71657d58da45d9d9 # SEE: https://github.com/gitleaks/gitleaks/pkgs/container/gitleaks +# docker/ghcr.io/gitleaks/gitleaks v8.24.0@sha256:2bcceac45179b3a91bff11a824d0fb952585b429e54fc928728b1d4d5c3e5176 # SEE: https://github.com/gitleaks/gitleaks/pkgs/container/gitleaks # docker/ghcr.io/igorshubovych/markdownlint-cli v0.37.0@sha256:fb3e79946fce78e1cde84d6798c6c2a55f2de11fc16606a40d49411e281d950d # SEE: https://github.com/igorshubovych/markdownlint-cli/pkgs/container/markdownlint-cli # docker/ghcr.io/make-ops-tools/gocloc latest@sha256:6888e62e9ae693c4ebcfed9f1d86c70fd083868acb8815fe44b561b9a73b5032 # SEE: https://github.com/make-ops-tools/gocloc/pkgs/container/gocloc # docker/ghcr.io/nhs-england-tools/github-runner-image 20230909-321fd1e-rt@sha256:ce4fd6035dc450a50d3cbafb4986d60e77cb49a71ab60a053bb1b9518139a646 # SEE: https://github.com/nhs-england-tools/github-runner-image/pkgs/container/github-runner-image diff --git a/infrastructure/terraform/bin/terraform.sh b/infrastructure/terraform/bin/terraform.sh index c17bae7ac..756b4ef8c 100755 --- a/infrastructure/terraform/bin/terraform.sh +++ b/infrastructure/terraform/bin/terraform.sh @@ -8,7 +8,7 @@ ## # Set Script Version ## -readonly script_ver="1.8.0"; +readonly script_ver="1.8.1"; ## # Standardised failure function @@ -399,13 +399,16 @@ fi; pushd "${component_path}"; readonly component_name=$(basename ${component_path}); -# Check for presence of tfenv (https://github.com/kamatama41/tfenv) -# and a .terraform-version file. If both present, ensure required -# version of terraform for this component is installed automagically. -tfenv_bin="$(which tfenv 2>/dev/null)"; -if [[ -n "${tfenv_bin}" && -x "${tfenv_bin}" && -f .terraform-version ]]; then - ${tfenv_bin} install; -fi; +# install terraform +# verify terraform version matches .tool-versions +echo ${PWD} +tool_version=$(grep "terraform " .tool-versions | cut -d ' ' -f 2) +asdf plugin-add terraform && asdf install terraform "${tool_version}" +current_version=$(terraform --version | head -n 1 | cut -d 'v' -f 2) + +if [ -z "${current_version}" ] || [ "${current_version}" != "${tool_version}" ]; then + error_and_die "Terraform version mismatch. Expected: ${tool_version}, Actual: ${current_version}" +fi # Regardless of bootstrapping or not, we'll be using this string. # If bootstrapping, we will fill it with variables, @@ -536,26 +539,24 @@ fi; [ -f "${dynamic_file_path}" ] && tf_var_file_paths+=("${dynamic_file_path}"); # Warn on duplication -if [ ${#tf_var_file_paths[@]} -gt 0 ]; then - duplicate_variables="$(cat "${tf_var_file_paths[@]}" | sed -n -e 's/\(^[a-zA-Z0-9_\-]\+\)\s*=.*$/\1/p' | sort | uniq -d)"; - [ -n "${duplicate_variables}" ] \ - && echo -e " - ################################################################### - # WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING # - ################################################################### - The following input variables appear to be duplicated: - - ${duplicate_variables} - - This could lead to unexpected behaviour. Overriding of variables - has previously been unpredictable and is not currently supported, - but it may work. - - Recent changes to terraform might give you useful overriding and - map-merging functionality, please use with caution and report back - on your successes & failures. - ###################################################################"; -fi +duplicate_variables="$(cat "${tf_var_file_paths[@]}" | sed -n -e 's/\(^[a-zA-Z0-9_\-]\+\)\s*=.*$/\1/p' | sort | uniq -d)"; +[ -n "${duplicate_variables}" ] \ + && echo -e " +################################################################### +# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING # +################################################################### +The following input variables appear to be duplicated: + +${duplicate_variables} + +This could lead to unexpected behaviour. Overriding of variables +has previously been unpredictable and is not currently supported, +but it may work. + +Recent changes to terraform might give you useful overriding and +map-merging functionality, please use with caution and report back +on your successes & failures. +###################################################################"; # Build up the tfvars arguments for terraform command line for file_path in "${tf_var_file_paths[@]}"; do diff --git a/scripts/config/.repository-template-sync-ignore b/scripts/config/.repository-template-sync-ignore index 7564f3e8d..2c23df7ab 100644 --- a/scripts/config/.repository-template-sync-ignore +++ b/scripts/config/.repository-template-sync-ignore @@ -1,7 +1,7 @@ # Files and folders to ignore when syncing nhs-notify-repository-template back in to this repository -scripts/config/.repository-template-sync-ignore .github/workflows/ nhs-notify-repository-template/ +.github/CODEOWNERS # Files and Folders in this repository to ignore .vscode/ @@ -9,6 +9,11 @@ CHANGELOG.md project.code-workspace README.md VERSION +.editorconfig +.gitleaksignore +scripts/tests/ +Makefile +scripts/config/sonar-scanner.properties # Files and Folders in the template repository to disregard .devcontainer/ @@ -16,3 +21,4 @@ VERSION */examples/ docs/ infrastructure/terraform/components/ +docker/examples/ diff --git a/scripts/config/.repository-template-sync-merge b/scripts/config/.repository-template-sync-merge new file mode 100644 index 000000000..549e19157 --- /dev/null +++ b/scripts/config/.repository-template-sync-merge @@ -0,0 +1,7 @@ +# Files and folders to merge when syncing nhs-notify-repository-template back in to this repository +scripts/config/.repository-template-sync-ignore +scripts/config/.repository-template-sync-merge +.tool-versions +.gitignore +scripts/config/vale/styles/config/vocabularies/words/accept.txt +scripts/config/vale/styles/config/vocabularies/words/reject.txt diff --git a/scripts/config/gitleaks.toml b/scripts/config/gitleaks.toml index af5f0bb71..7b8360ae8 100644 --- a/scripts/config/gitleaks.toml +++ b/scripts/config/gitleaks.toml @@ -1,4 +1,5 @@ # SEE: https://github.com/gitleaks/gitleaks/#configuration +# Do not edit this file directly as it will be overwritten by changes from the nhs-notify-repository-template on next sync [extend] useDefault = true # SEE: https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml @@ -16,4 +17,15 @@ regexes = [ ] [allowlist] -paths = ['''.terraform.lock.hcl''', '''poetry.lock''', '''yarn.lock'''] +paths = [ + '''.terraform.lock.hcl''', + '''poetry.lock''', + '''yarn.lock''', + '''Gemfile.lock''', +] + +# Exclude Chrome version in user agent +regexTarget = "line" +regexes = [ + '''Chrome/[\d.]+''' +] diff --git a/scripts/config/pre-commit.yaml b/scripts/config/pre-commit.yaml index da31ce7c7..de68260bf 100644 --- a/scripts/config/pre-commit.yaml +++ b/scripts/config/pre-commit.yaml @@ -1,43 +1,62 @@ repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 # Use the ref you want to point at + hooks: + - id: trailing-whitespace + - id: detect-aws-credentials + args: [--allow-missing-credentials] + - id: check-added-large-files + - id: check-symlinks + - id: detect-private-key + - id: end-of-file-fixer + exclude: .+\.cs + - id: forbid-new-submodules + - id: mixed-line-ending + - id: pretty-format-json + args: ['--autofix'] + # - id: ... - repo: local hooks: - - id: scan-secrets - name: Scan secrets - entry: ./scripts/githooks/scan-secrets.sh - args: ["check=staged-changes"] - language: script - pass_filenames: false + - id: sort-dictionary + name: Sort dictionary + entry: ./scripts/githooks/sort-dictionary.sh + language: script + pass_filenames: false - repo: local hooks: - - id: check-file-format - name: Check file format - entry: ./scripts/githooks/check-file-format.sh - args: ["check=staged-changes"] - language: script - pass_filenames: false + - id: scan-secrets + name: Scan secrets + entry: /usr/bin/env check=whole-history ./scripts/githooks/scan-secrets.sh + language: script + pass_filenames: false - repo: local hooks: - - id: check-markdown-format - name: Check Markdown format - entry: ./scripts/githooks/check-markdown-format.sh - args: ["check=staged-changes"] - language: script - pass_filenames: false + - id: check-file-format + name: Check file format + entry: /usr/bin/env check=branch ./scripts/githooks/check-file-format.sh + language: script + pass_filenames: false - repo: local hooks: - - id: check-english-usage - name: Check English usage - entry: ./scripts/githooks/check-english-usage.sh - args: ["check=staged-changes"] - language: script - pass_filenames: false + - id: check-markdown-format + name: Check Markdown format + entry: /usr/bin/env check=branch ./scripts/githooks/check-markdown-format.sh + language: script + pass_filenames: false - repo: local hooks: - - id: lint-terraform - name: Lint Terraform - entry: ./scripts/githooks/check-terraform-format.sh - language: script - pass_filenames: false + - id: check-english-usage + name: Check English usage + entry: /usr/bin/env check=branch ./scripts/githooks/check-english-usage.sh + language: script + pass_filenames: false + - repo: local + hooks: + - id: lint-terraform + name: Lint Terraform + entry: ./scripts/githooks/check-terraform-format.sh + language: script + pass_filenames: false - repo: local hooks: - id: generate-terraform-docs diff --git a/scripts/config/sonar-scanner.properties b/scripts/config/sonar-scanner.properties index eef115008..5dfb63dd1 100644 --- a/scripts/config/sonar-scanner.properties +++ b/scripts/config/sonar-scanner.properties @@ -12,3 +12,4 @@ sonar.coverage.exclusions=tests/, frontend/src/__tests__, frontend/src/**/*.dev. #sonar.python.coverage.reportPaths=.coverage/coverage.xml sonar.javascript.lcov.reportPaths=lcov.info +sonar.coverage.exclusions=scripts/**/* diff --git a/scripts/git-repo/auto-link.md b/scripts/git-repo/auto-link.md new file mode 100644 index 000000000..dfb68a64b --- /dev/null +++ b/scripts/git-repo/auto-link.md @@ -0,0 +1,11 @@ +# GitHub + +## Auto link Protection Rules + +This will create the auto link to Jira. + +```sh +./auto-link.sh $reponame $PAT +``` + +PAT must have `administration:write`. [Create an auto link](https://docs.github.com/en/rest/repos/autolinks?apiVersion=2022-11-28#create-an-autolink-for-a-repository) diff --git a/scripts/git-repo/auto-link.sh b/scripts/git-repo/auto-link.sh new file mode 100644 index 000000000..a827bd076 --- /dev/null +++ b/scripts/git-repo/auto-link.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $2" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/NHSDigital/$1/autolinks \ + -d '{"key_prefix":"CCM-","url_template":" https://nhsd-jira.digital.nhs.uk/browse/CCM-","is_alphanumeric":true}' diff --git a/scripts/git-repo/branch-protection.md b/scripts/git-repo/branch-protection.md new file mode 100644 index 000000000..0e513f86e --- /dev/null +++ b/scripts/git-repo/branch-protection.md @@ -0,0 +1,11 @@ +# GitHub + +## Branch Protection Rules + +This will create the default branch protection rules using GitHub API. + +```sh +./branch-protection.sh $reponame $PAT +``` + +PAT must have `administration:write`. [Create a repository rule set](https://docs.github.com/en/rest/repos/rules?apiVersion=2022-11-28#create-a-repository-ruleset) diff --git a/scripts/git-repo/branch-protection.sh b/scripts/git-repo/branch-protection.sh new file mode 100755 index 000000000..f98597a47 --- /dev/null +++ b/scripts/git-repo/branch-protection.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +curl --location "https://api.github.com/repos/NHSDigital/$1/rulesets" \ +--header 'X-GitHub-Api-Version: 2022-11-28' \ +--header 'Accept: application/vnd.github+json' \ +--header "Authorization: Bearer $2" \ +--header 'Content-Type: application/json' \ +--data '{ + "name": "nhs-notify-default", + "target": "branch", + "enforcement": "active", + "conditions": { + "ref_name": { + "exclude": [], + "include": [ + "~DEFAULT_BRANCH" + ] + } + }, + "rules": [ + { + "type": "deletion" + }, + { + "type": "non_fast_forward" + }, + { + "type": "pull_request", + "parameters": { + "required_approving_review_count": 1, + "dismiss_stale_reviews_on_push": true, + "require_code_owner_review": true, + "require_last_push_approval": true, + "required_review_thread_resolution": true + } + }, + { + "type": "required_signatures" + }, + { + "type": "required_status_checks", + "parameters": { + "strict_required_status_checks_policy": true, + "required_status_checks": [] + } + } + ] +}' diff --git a/scripts/githooks/check-markdown-format.sh b/scripts/githooks/check-markdown-format.sh index 698df4a57..c39a080d4 100755 --- a/scripts/githooks/check-markdown-format.sh +++ b/scripts/githooks/check-markdown-format.sh @@ -38,7 +38,7 @@ function main() { check=${check:-working-tree-changes} case $check in "all") - files="$(find ./ -type f -name "*.md")" + files="$(git ls-files "*.md")" ;; "staged-changes") files="$(git diff --diff-filter=ACMRT --name-only --cached "*.md")" diff --git a/scripts/githooks/sort-dictionary.sh b/scripts/githooks/sort-dictionary.sh new file mode 100755 index 000000000..45a395292 --- /dev/null +++ b/scripts/githooks/sort-dictionary.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -euo pipefail + +# Pre-commit git hook to sort the Vale dictionary in a consistent manner to avoid future merge conflicts and aid insertion of new terms +# +# Usage: +# $ [options] ./sort-dictionary.sh +# +# Options: +# +# +# Exit codes: +# 0 - Successfully sorted the dictionary +# non-zero - failed to sort dictionary + +# ============================================================================== + +function main() { + root=scripts/config/vale/styles/config/vocabularies/words + opts="--dictionary-order --ignore-case -s" + sort $opts $root/accept.txt > $root/accept.sorted.txt + sort $opts $root/reject.txt > $root/reject.sorted.txt + + mv $root/accept.sorted.txt $root/accept.txt + mv $root/reject.sorted.txt $root/reject.txt + + git add -uv $root/* +} + +# ============================================================================== + +function is-arg-true() { + + if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then + return 0 + else + return 1 + fi +} + +# ============================================================================== + +is-arg-true "${VERBOSE:-false}" && set -x + +main "$@" + +exit 0 diff --git a/scripts/githooks/sync-template-repo.sh b/scripts/githooks/sync-template-repo.sh index 060aaa4c2..0d23e52f3 100755 --- a/scripts/githooks/sync-template-repo.sh +++ b/scripts/githooks/sync-template-repo.sh @@ -5,7 +5,7 @@ set -euo pipefail # Script to synchronise the nhs-notify-template-repository with this repository # # Usage: -# $ [options] ./check-terraform-format.sh +# $ [options] ./sync-template-repo.sh # # Options: # new_only=true # Only identify new files from the template-repository @@ -13,13 +13,16 @@ set -euo pipefail # ============================================================================== -# Command line prameters +scriptdir=$(realpath "$(dirname "$0")") + +# Command line parameters new_only=${new_only:-false} changes_only=${changes_only:-false} # Set variables TEMPLATE_REPO_DIR="nhs-notify-repository-template" IGNORE_FILE="scripts/config/.repository-template-sync-ignore" +MERGE_FILE="scripts/config/.repository-template-sync-merge" # Check if the template directory exists if [ ! -d "${TEMPLATE_REPO_DIR}" ]; then @@ -34,11 +37,21 @@ if [ ! -f "${IGNORE_FILE}" ]; then echo "# Files and Folders in the template repository to disregard" >> ${IGNORE_FILE} fi +# Check if the .template-merge file exists, create an empty one if not +if [ ! -f "${MERGE_FILE}" ]; then + echo "# Files and folders to merge when syncing ${TEMPLATE_REPO_DIR} back in to this repository" > ${MERGE_FILE} +fi + # Read the .template-ignore file into an array while IFS= read -r line || [ -n "$line" ]; do IGNORED_PATHS+=("$line") done < "$IGNORE_FILE" +# Read the .template-merge file into an array +while IFS= read -r line || [ -n "$line" ]; do + MERGED_PATHS+=("$line") +done < "$MERGE_FILE" + # Check if a file is ignored. is_ignored() { local file=${1} @@ -56,13 +69,24 @@ is_ignored() { return 1 } +is_merge() { + local file=${1} + + for merged in "${MERGED_PATHS[@]}"; do + if [[ -n "$merged" && "$file" =~ $merged ]]; then + return 0 + fi + done + return 1 +} + # Navigate to the template directory cd "${TEMPLATE_REPO_DIR}" || exit FILES_ADDED=() FILES_WITH_CHANGES=() # Loop through all files in the template directory -while IFS= read -r -d '' file; do +while IFS= read -r -d '' file || [[ -n $file ]]; do relative_path="${file#./}" # Remove leading './' # Check if the file is ignored @@ -84,27 +108,38 @@ while IFS= read -r -d '' file; do # If the file exists, check if it's different if [ "$new_only" == false ]; then if ! diff -q "$file" "$target_path" > /dev/null 2>&1; then - echo "Merging changes from $relative_path" - FILES_WITH_CHANGES+=("${relative_path}") - cp "$file" "$target_path" + if is_merge "$relative_path"; then + echo "Merging changes from $relative_path" + cp "$target_path" "${target_path}.bak" + node "${scriptdir}/../maintenance/merge.js" "$target_path" "$file" > "${target_path}.merged" + if ! cmp -s "${target_path}.merged" "${target_path}.bak"; then + FILES_WITH_CHANGES+=("${relative_path}") + mv "${target_path}.merged" "$target_path" + fi + rm -f "${target_path}.merged" "${target_path}.bak" + else + echo "Copying changes from $relative_path" + cp "$file" "$target_path" + FILES_WITH_CHANGES+=("${relative_path}") + fi fi fi fi done < <(find . -type f -print0) -echo "${#FILES_ADDED[@]}" files added, "${#FILES_WITH_CHANGES[@]}" files with changes detected. - echo ------------------------------------------ +echo "${#FILES_ADDED[@]} files added, ${#FILES_WITH_CHANGES[@]} files with changes detected." -if [ "$changes_only" == false ]; then +if [[ "$changes_only" == false && ${#FILES_ADDED[@]} -gt 0 ]]; then echo ------------------------------------------ echo "New files added:" printf ' - %s\n' "${FILES_ADDED[@]}" fi - -if [ "$new_only" == false ]; then +if [[ "$new_only" == false && ${#FILES_WITH_CHANGES[@]} -gt 0 ]]; then echo ------------------------------------------ echo "Changed files:" printf ' - %s\n' "${FILES_WITH_CHANGES[@]}" fi + +echo ------------------------------------------ diff --git a/scripts/maintenance/merge.js b/scripts/maintenance/merge.js new file mode 100644 index 000000000..8f5bd6cc7 --- /dev/null +++ b/scripts/maintenance/merge.js @@ -0,0 +1,81 @@ +/******************************************************************************* + * Script to merge all added lines from source to target. + * Modified lines will be left intact. + * + * This is intended for updating config files like .tool-versions and .gitignore + * where the first token on the line remains the same + * + * Usage: + * $ node merge.js + * + * Output: + * Outputs the merged file to stdout + * + *******************************************************************************/ + +const fs = require("fs"); + +// Read files +const [file1, file2] = process.argv.slice(2); +const lines1 = fs.readFileSync(file1).toString().split('\n'); +const lines2 = fs.readFileSync(file2).toString().split('\n'); + +// Tokenize lines in file1 for later comparison +const tokenize = line => { + if (line === '') { + return []; + } + return line.split(/\s+|[:=]/).filter(x => x !== '#' && x !== '').slice(0, 1); +}; +const lines1Tokens = lines1.flatMap(tokenize); + +// Step through the files +let pos1 = 0, pos2 = 0; +while (pos1 < lines1.length || pos2 < lines2.length) { + + const l1 = pos1 < lines1.length && lines1[pos1] || ''; + const l2 = pos2 < lines2.length && lines2[pos2] || ''; + + // If the lines match, print l1 and skip l2 + if (l1 !== '' && l1 === l2) { + process.stdout.write(`${l1}\n`); + pos1++; + pos2++; + continue; + } + + if (pos2 < lines2.length) { + // If l2 is empty, skip l2 + if (l2 === '') { + pos2++; + continue; + } + + const [l2token] = tokenize(l2); + + // If l2 token matches l1 token, print l1 + if (pos1 < lines1.length && lines1Tokens[pos1] === l2token) { + process.stdout.write(`${l1}\n`); + pos1++; + pos2++; + continue; + } + + // If l2 doesn't match any lines in file1, print l2 + if (l2token && !lines1Tokens.includes(l2token)) { + process.stdout.write(`${l2}\n`); + } + pos2++ + continue; + } + + // If we're not at the end of file1, print l1 + if (pos1 < lines1.length) { + if (pos1 === lines1.length - 1 && l1 === '') { + // Don't print tailing newline + } else { + process.stdout.write(`${l1}\n`); + } + pos1++; + } +} From 384ed907a6a28d53e8c75a054faa505c759d8f06 Mon Sep 17 00:00:00 2001 From: m-houston <60653100+m-houston@users.noreply.github.com> Date: Mon, 10 Mar 2025 17:14:43 +0000 Subject: [PATCH 2/2] Drift from template --- .github/actions/create-lines-of-code-report/action.yaml | 2 +- .github/actions/scan-dependencies/action.yaml | 2 +- scripts/config/gitleaks.toml | 1 - scripts/init.mk | 4 ++-- scripts/maintenance/merge.js | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/actions/create-lines-of-code-report/action.yaml b/.github/actions/create-lines-of-code-report/action.yaml index 86396f7ae..b21f06670 100644 --- a/.github/actions/create-lines-of-code-report/action.yaml +++ b/.github/actions/create-lines-of-code-report/action.yaml @@ -44,7 +44,7 @@ runs: echo "secrets_exist=${{ inputs.idp_aws_report_upload_role_name != '' && inputs.idp_aws_report_upload_bucket_endpoint != '' }}" >> $GITHUB_OUTPUT - name: "Authenticate to send the report" if: steps.check.outputs.secrets_exist == 'true' - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: arn:aws:iam::${{ inputs.idp_aws_report_upload_account_id }}:role/${{ inputs.idp_aws_report_upload_role_name }} aws-region: ${{ inputs.idp_aws_report_upload_region }} diff --git a/.github/actions/scan-dependencies/action.yaml b/.github/actions/scan-dependencies/action.yaml index 1000df147..f8ed605d0 100644 --- a/.github/actions/scan-dependencies/action.yaml +++ b/.github/actions/scan-dependencies/action.yaml @@ -58,7 +58,7 @@ runs: run: echo "secrets_exist=${{ inputs.idp_aws_report_upload_role_name != '' && inputs.idp_aws_report_upload_bucket_endpoint != '' }}" >> $GITHUB_OUTPUT - name: "Authenticate to send the reports" if: steps.check.outputs.secrets_exist == 'true' - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: arn:aws:iam::${{ inputs.idp_aws_report_upload_account_id }}:role/${{ inputs.idp_aws_report_upload_role_name }} aws-region: ${{ inputs.idp_aws_report_upload_region }} diff --git a/scripts/config/gitleaks.toml b/scripts/config/gitleaks.toml index 7b8360ae8..188bfdf09 100644 --- a/scripts/config/gitleaks.toml +++ b/scripts/config/gitleaks.toml @@ -1,5 +1,4 @@ # SEE: https://github.com/gitleaks/gitleaks/#configuration -# Do not edit this file directly as it will be overwritten by changes from the nhs-notify-repository-template on next sync [extend] useDefault = true # SEE: https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml diff --git a/scripts/init.mk b/scripts/init.mk index e12255c34..373f8a4f4 100644 --- a/scripts/init.mk +++ b/scripts/init.mk @@ -7,7 +7,7 @@ include scripts/tests/test.mk # ============================================================================== runner-act: # Run GitHub Actions locally - mandatory: workflow=[workflow file name], job=[job name] @Development - . ./scripts/docker/docker.lib.sh + source ./scripts/docker/docker.lib.sh act $(shell [[ "${VERBOSE}" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$$ ]] && echo --verbose) \ --container-architecture linux/amd64 \ --platform ubuntu-latest=$$(name="ghcr.io/nhs-england-tools/github-runner-image" docker-get-image-version-and-pull) \ @@ -21,7 +21,7 @@ runner-act: # Run GitHub Actions locally - mandatory: workflow=[workflow file na --job ${job} version-create-effective-file: # Create effective version file - optional: dir=[path to the VERSION file to use, default is '.'], BUILD_DATETIME=[build date and time in the '%Y-%m-%dT%H:%M:%S%z' format generated by the CI/CD pipeline, default is current date and time] @Development - . ./scripts/docker/docker.lib.sh + source scripts/docker/docker.lib.sh version-create-effective-file shellscript-lint-all: # Lint all shell scripts in this project, do not fail on error, just print the error messages @Quality diff --git a/scripts/maintenance/merge.js b/scripts/maintenance/merge.js index 8f5bd6cc7..28e2c45bd 100644 --- a/scripts/maintenance/merge.js +++ b/scripts/maintenance/merge.js @@ -25,7 +25,7 @@ const tokenize = line => { if (line === '') { return []; } - return line.split(/\s+|[:=]/).filter(x => x !== '#' && x !== '').slice(0, 1); + return line.split(/\s+/).filter(x => x !== '#').slice(0, 1); }; const lines1Tokens = lines1.flatMap(tokenize);