diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b2d41f4..83cfb67 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ # Default owner for everything in this repo. -* @ExtraToast +* @JorisJonkers-dev diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index fc03553..3ff250f 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - - name: ExtraToast platform conventions - url: https://github.com/ExtraToast/repo-template/blob/main/CONTRIBUTING.md + - name: JorisJonkers-dev platform conventions + url: https://github.com/JorisJonkers-dev/repo-template/blob/main/CONTRIBUTING.md about: Branch, PR, CI (Pipeline Complete) and versioning conventions for every repo. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5d89961..8426e88 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,4 @@ -# Renovate (renovate.json) is the primary dependency manager for ExtraToast +# Renovate (renovate.json) is the primary dependency manager for JorisJonkers-dev # repos. Dependabot is enabled only for GitHub Actions security updates as a # belt-and-braces fallback; disable this file if Renovate covers actions in a # given repo. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb9229a..816b7b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -# Canonical single CI workflow for every ExtraToast repository. +# Canonical single CI workflow for every JorisJonkers-dev repository. # # Org convention: ONE pipeline per repo, and it terminates in a single # aggregating job named "Pipeline Complete". That job name is the ONLY diff --git a/.github/workflows/container-publish.yml b/.github/workflows/container-publish.yml new file mode 100644 index 0000000..545993f --- /dev/null +++ b/.github/workflows/container-publish.yml @@ -0,0 +1,92 @@ +name: Container Publish + +on: + workflow_call: + inputs: + image-name: + description: Image name below ghcr.io//. + required: true + type: string + version: + description: Release version tag. + required: true + type: string + context: + description: Docker build context. + required: false + type: string + default: . + dockerfile: + description: Dockerfile path. + required: false + type: string + default: Dockerfile + platforms: + description: Target platforms. + required: false + type: string + default: linux/amd64 + secrets: + packages-token: + description: Token passed as docker build secret github_token. + required: false + +permissions: + contents: read + packages: write + +jobs: + publish: + name: Container Publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: docker/setup-qemu-action@v3 + + - uses: docker/setup-buildx-action@v4 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Resolve image tags + id: image + shell: bash + env: + IMAGE_NAME: ${{ inputs.image-name }} + VERSION: ${{ inputs.version }} + GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} + run: | + set -euo pipefail + + owner="$(printf '%s' "$GITHUB_REPOSITORY_OWNER" | tr '[:upper:]' '[:lower:]')" + image_ref="ghcr.io/${owner}/${IMAGE_NAME}" + if [ "$image_ref" != "$(printf '%s' "$image_ref" | tr '[:upper:]' '[:lower:]')" ]; then + echo "::error::Docker image reference must be lowercase: $image_ref" + exit 1 + fi + + { + echo 'tags<> "$GITHUB_OUTPUT" + + - name: Build and publish image + uses: docker/build-push-action@v7 + with: + context: ${{ inputs.context }} + file: ${{ inputs.dockerfile }} + platforms: ${{ inputs.platforms }} + push: true + tags: ${{ steps.image.outputs.tags }} + cache-from: type=gha,scope=${{ inputs.image-name }} + cache-to: type=gha,mode=max,scope=${{ inputs.image-name }} + secrets: | + github_token=${{ secrets.packages-token || github.token }} + github_actor=${{ github.actor }} diff --git a/.github/workflows/deploy-config-render-drift.yml b/.github/workflows/deploy-config-render-drift.yml index ff5409b..33fa52a 100644 --- a/.github/workflows/deploy-config-render-drift.yml +++ b/.github/workflows/deploy-config-render-drift.yml @@ -4,7 +4,7 @@ on: workflow_call: inputs: package-version: - description: Version of @extratoast/deploy-config-schema to install. + description: Version of @jorisjonkers-dev/deploy-config-schema to install. required: false type: string default: ^0.6.0 @@ -22,7 +22,7 @@ on: type: string default: . node-auth-token: - description: Token with packages:read for installing @extratoast packages from GitHub Packages (pass secrets.GITHUB_TOKEN). + description: Token with packages:read for installing @jorisjonkers-dev packages from GitHub Packages (pass secrets.GITHUB_TOKEN). required: false type: string default: "" @@ -56,7 +56,7 @@ jobs: - uses: actions/checkout@v6 with: - repository: ExtraToast/github-workflows + repository: JorisJonkers-dev/github-workflows ref: ${{ steps.workflow-ref.outputs.ref }} path: .github-workflows persist-credentials: false diff --git a/.github/workflows/docker-image-ci.yml b/.github/workflows/docker-image-ci.yml new file mode 100644 index 0000000..8f1dd6f --- /dev/null +++ b/.github/workflows/docker-image-ci.yml @@ -0,0 +1,79 @@ +name: Docker Image CI + +on: + workflow_call: + inputs: + image-name: + description: Image name below ghcr.io//. + required: true + type: string + context: + description: Docker build context. + required: false + type: string + default: . + dockerfile: + description: Dockerfile path. + required: false + type: string + default: Dockerfile + target: + description: Optional Dockerfile target. + required: false + type: string + default: '' + build-args: + description: Optional docker build args, one per line. + required: false + type: string + default: '' + secrets: + packages-token: + description: Token passed as docker build secret github_token. + required: false + +permissions: + contents: read + packages: read + +jobs: + build: + name: Docker Image CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: docker/setup-buildx-action@v4 + + - name: Resolve image reference + id: image + shell: bash + env: + IMAGE_NAME: ${{ inputs.image-name }} + GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} + run: | + set -euo pipefail + + owner="$(printf '%s' "$GITHUB_REPOSITORY_OWNER" | tr '[:upper:]' '[:lower:]')" + image_ref="ghcr.io/${owner}/${IMAGE_NAME}" + if [ "$image_ref" != "$(printf '%s' "$image_ref" | tr '[:upper:]' '[:lower:]')" ]; then + echo "::error::Docker image reference must be lowercase: $image_ref" + exit 1 + fi + + printf 'tag=%s:ci-%s\n' "$image_ref" "$GITHUB_SHA" >> "$GITHUB_OUTPUT" + + - name: Build image + uses: docker/build-push-action@v7 + with: + context: ${{ inputs.context }} + file: ${{ inputs.dockerfile }} + target: ${{ inputs.target }} + build-args: ${{ inputs.build-args }} + push: false + tags: ${{ steps.image.outputs.tag }} + cache-from: type=gha,scope=${{ inputs.image-name }} + cache-to: type=gha,mode=max,scope=${{ inputs.image-name }} + secrets: | + github_token=${{ secrets.packages-token || github.token }} + github_actor=${{ github.actor }} diff --git a/.github/workflows/flux-render-validate.yml b/.github/workflows/flux-render-validate.yml index 4c439da..9d46b96 100644 --- a/.github/workflows/flux-render-validate.yml +++ b/.github/workflows/flux-render-validate.yml @@ -16,7 +16,7 @@ on: description: Repository containing the CRD catalog and validation script. required: false type: string - default: ExtraToast/platform-blueprints + default: JorisJonkers-dev/platform-blueprints crd-catalog-ref: description: Git ref for the CRD catalog and validation script. required: false @@ -56,7 +56,7 @@ jobs: - uses: actions/checkout@v6 with: - repository: ExtraToast/github-workflows + repository: JorisJonkers-dev/github-workflows ref: ${{ steps.workflow-ref.outputs.ref }} path: .github-workflows persist-credentials: false diff --git a/.github/workflows/gitops-ci.yml b/.github/workflows/gitops-ci.yml new file mode 100644 index 0000000..5ddc6d6 --- /dev/null +++ b/.github/workflows/gitops-ci.yml @@ -0,0 +1,95 @@ +name: GitOps CI + +on: + workflow_call: + inputs: + overlay-paths: + description: Newline- or comma-separated kustomize overlay paths to render and validate. + required: true + type: string + platform-config-paths: + description: Newline- or comma-separated platform config globs to validate. + required: false + type: string + default: |- + inventory/**/*.yaml + inventory/**/*.yml + deploy-config-command: + description: Optional command that writes deploy-config JSON to DEPLOY_CONFIG_OUT. + required: false + type: string + default: '' + deploy-config-targets: + description: Optional newline-separated adapter=relative/committed/path.yaml render drift targets. + required: false + type: string + default: '' + system-tests-command: + description: Optional caller-owned system test command. + required: false + type: string + default: '' + secrets: + packages-token: + description: GitHub Packages token used for deploy-config-schema package resolution. + required: false + +permissions: + contents: read + packages: read + +jobs: + gitops: + name: GitOps CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Resolve workflow ref + id: workflow-ref + shell: bash + env: + WORKFLOW_REF: ${{ github.workflow_ref }} + run: | + set -euo pipefail + + ref="${WORKFLOW_REF#*@}" + if [ -z "$ref" ] || [ "$ref" = "$WORKFLOW_REF" ]; then + echo "::error::Unable to resolve reusable workflow ref from $WORKFLOW_REF" + exit 1 + fi + + printf 'ref=%s\n' "$ref" >> "$GITHUB_OUTPUT" + + - uses: actions/checkout@v6 + with: + repository: JorisJonkers-dev/github-workflows + ref: ${{ steps.workflow-ref.outputs.ref }} + path: .github-workflows + persist-credentials: false + + - name: Validate platform config + uses: ./.github-workflows/actions/platform-config-validate + with: + config-paths: ${{ inputs.platform-config-paths }} + schema-kind: auto + node-auth-token: ${{ secrets.packages-token || github.token }} + + - name: Validate Flux render + uses: ./.github-workflows/actions/flux-render-validate + with: + overlay-paths: ${{ inputs.overlay-paths }} + + - name: Check deploy config render drift + if: ${{ inputs.deploy-config-command != '' && inputs.deploy-config-targets != '' }} + uses: ./.github-workflows/actions/deploy-config-render-drift + with: + deploy-config-command: ${{ inputs.deploy-config-command }} + targets: ${{ inputs.deploy-config-targets }} + node-auth-token: ${{ secrets.packages-token || github.token }} + + - name: Run system tests + if: ${{ inputs.system-tests-command != '' }} + env: + SYSTEM_TESTS_COMMAND: ${{ inputs.system-tests-command }} + run: bash -euo pipefail -c "$SYSTEM_TESTS_COMMAND" diff --git a/.github/workflows/jvm-ci.yml b/.github/workflows/jvm-ci.yml index 054b4a8..5592dcc 100644 --- a/.github/workflows/jvm-ci.yml +++ b/.github/workflows/jvm-ci.yml @@ -76,7 +76,7 @@ jobs: - uses: actions/checkout@v6 with: - repository: ExtraToast/github-workflows + repository: JorisJonkers-dev/github-workflows ref: ${{ steps.workflow-ref.outputs.ref }} path: .github-workflows persist-credentials: false @@ -115,7 +115,7 @@ jobs: - uses: actions/checkout@v6 with: - repository: ExtraToast/github-workflows + repository: JorisJonkers-dev/github-workflows ref: ${{ steps.workflow-ref.outputs.ref }} path: .github-workflows persist-credentials: false diff --git a/.github/workflows/migration-guard.yml b/.github/workflows/migration-guard.yml index f4f462b..f7590de 100644 --- a/.github/workflows/migration-guard.yml +++ b/.github/workflows/migration-guard.yml @@ -55,7 +55,7 @@ jobs: - uses: actions/checkout@v6 with: - repository: ExtraToast/github-workflows + repository: JorisJonkers-dev/github-workflows ref: ${{ steps.workflow-ref.outputs.ref }} path: .github-workflows persist-credentials: false diff --git a/.github/workflows/nix-ci.yml b/.github/workflows/nix-ci.yml new file mode 100644 index 0000000..8387db1 --- /dev/null +++ b/.github/workflows/nix-ci.yml @@ -0,0 +1,46 @@ +name: Nix CI + +on: + workflow_call: + inputs: + flake-path: + description: Directory that contains the flake. + required: false + type: string + default: . + check-command: + description: Nix check command. + required: false + type: string + default: nix flake check --print-build-logs + validate-command: + description: Optional extra validation command. + required: false + type: string + default: '' + +permissions: + contents: read + +jobs: + nix: + name: Nix CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: cachix/install-nix-action@v31 + + - name: Validate + if: ${{ inputs.validate-command != '' }} + working-directory: ${{ inputs.flake-path }} + env: + VALIDATE_COMMAND: ${{ inputs.validate-command }} + run: bash -euo pipefail -c "$VALIDATE_COMMAND" + + - name: Check flake + if: ${{ inputs.check-command != '' }} + working-directory: ${{ inputs.flake-path }} + env: + CHECK_COMMAND: ${{ inputs.check-command }} + run: bash -euo pipefail -c "$CHECK_COMMAND" diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml new file mode 100644 index 0000000..0ca1683 --- /dev/null +++ b/.github/workflows/node-ci.yml @@ -0,0 +1,131 @@ +name: Node CI + +on: + workflow_call: + inputs: + node-version: + description: Node.js version to install. + required: false + type: string + default: '24' + package-manager: + description: Package manager to configure. Supported values are npm, pnpm, and yarn. + required: false + type: string + default: pnpm + working-directory: + description: Directory that contains the Node package. + required: false + type: string + default: . + install-command: + description: Dependency install command. Empty uses the setup-node action default for the package manager. + required: false + type: string + default: '' + lint-command: + description: Optional lint command. + required: false + type: string + default: '' + typecheck-command: + description: Optional typecheck command. + required: false + type: string + default: '' + test-command: + description: Optional test command. + required: false + type: string + default: '' + build-command: + description: Optional build command. + required: false + type: string + default: '' + package-check-command: + description: Optional package validation command. + required: false + type: string + default: '' + secrets: + packages-token: + description: GitHub Packages token used for npm package resolution. + required: false + +permissions: + contents: read + packages: read + +jobs: + node: + name: Node CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Resolve workflow ref + id: workflow-ref + shell: bash + env: + WORKFLOW_REF: ${{ github.workflow_ref }} + run: | + set -euo pipefail + + ref="${WORKFLOW_REF#*@}" + if [ -z "$ref" ] || [ "$ref" = "$WORKFLOW_REF" ]; then + echo "::error::Unable to resolve reusable workflow ref from $WORKFLOW_REF" + exit 1 + fi + + printf 'ref=%s\n' "$ref" >> "$GITHUB_OUTPUT" + + - uses: actions/checkout@v6 + with: + repository: JorisJonkers-dev/github-workflows + ref: ${{ steps.workflow-ref.outputs.ref }} + path: .github-workflows + persist-credentials: false + + - uses: ./.github-workflows/actions/setup-node + with: + node-version: ${{ inputs.node-version }} + package-manager: ${{ inputs.package-manager }} + working-directory: ${{ inputs.working-directory }} + install-command: ${{ inputs.install-command }} + github-packages-token: ${{ secrets.packages-token || github.token }} + + - name: Package check + if: ${{ inputs.package-check-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + PACKAGE_CHECK_COMMAND: ${{ inputs.package-check-command }} + run: bash -euo pipefail -c "$PACKAGE_CHECK_COMMAND" + + - name: Lint + if: ${{ inputs.lint-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + LINT_COMMAND: ${{ inputs.lint-command }} + run: bash -euo pipefail -c "$LINT_COMMAND" + + - name: Typecheck + if: ${{ inputs.typecheck-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + TYPECHECK_COMMAND: ${{ inputs.typecheck-command }} + run: bash -euo pipefail -c "$TYPECHECK_COMMAND" + + - name: Test + if: ${{ inputs.test-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + TEST_COMMAND: ${{ inputs.test-command }} + run: bash -euo pipefail -c "$TEST_COMMAND" + + - name: Build + if: ${{ inputs.build-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + BUILD_COMMAND: ${{ inputs.build-command }} + run: bash -euo pipefail -c "$BUILD_COMMAND" diff --git a/.github/workflows/platform-config-validate.yml b/.github/workflows/platform-config-validate.yml index 9cca388..5c0c02d 100644 --- a/.github/workflows/platform-config-validate.yml +++ b/.github/workflows/platform-config-validate.yml @@ -16,12 +16,12 @@ on: type: string default: auto package-version: - description: Version of @extratoast/deploy-config-schema to install. + description: Version of @jorisjonkers-dev/deploy-config-schema to install. required: false type: string default: 0.3.0 node-auth-token: - description: Token with packages:read for installing @extratoast packages from GitHub Packages (pass secrets.GITHUB_TOKEN). + description: Token with packages:read for installing @jorisjonkers-dev packages from GitHub Packages (pass secrets.GITHUB_TOKEN). required: false type: string default: "" @@ -65,7 +65,7 @@ jobs: - uses: actions/checkout@v6 with: - repository: ExtraToast/github-workflows + repository: JorisJonkers-dev/github-workflows ref: ${{ steps.workflow-ref.outputs.ref }} path: .github-workflows persist-credentials: false diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml new file mode 100644 index 0000000..d92bde4 --- /dev/null +++ b/.github/workflows/python-ci.yml @@ -0,0 +1,65 @@ +name: Python CI + +on: + workflow_call: + inputs: + python-version: + description: Python version to install. + required: false + type: string + default: '3.13' + install-command: + description: Dependency install command. + required: false + type: string + default: python -m pip install -r requirements-dev.txt + lint-command: + description: Lint command. + required: false + type: string + default: ruff check . + test-command: + description: Test command. + required: false + type: string + default: python -m unittest discover + working-directory: + description: Directory that contains the Python project. + required: false + type: string + default: . + +permissions: + contents: read + +jobs: + python: + name: Python CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-python@v6 + with: + python-version: ${{ inputs.python-version }} + + - name: Install dependencies + if: ${{ inputs.install-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + INSTALL_COMMAND: ${{ inputs.install-command }} + run: bash -euo pipefail -c "$INSTALL_COMMAND" + + - name: Lint + if: ${{ inputs.lint-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + LINT_COMMAND: ${{ inputs.lint-command }} + run: bash -euo pipefail -c "$LINT_COMMAND" + + - name: Test + if: ${{ inputs.test-command != '' }} + working-directory: ${{ inputs.working-directory }} + env: + TEST_COMMAND: ${{ inputs.test-command }} + run: bash -euo pipefail -c "$TEST_COMMAND" diff --git a/.gitleaks.toml b/.gitleaks.toml index c5bc1db..a6185fd 100644 --- a/.gitleaks.toml +++ b/.gitleaks.toml @@ -1,6 +1,6 @@ -# gitleaks config for ExtraToast repos. Extends the upstream default ruleset; +# gitleaks config for JorisJonkers-dev repos. Extends the upstream default ruleset; # add repo-specific allowlist entries below for known-safe test fixtures. -title = "ExtraToast gitleaks config" +title = "JorisJonkers-dev gitleaks config" [extend] useDefault = true diff --git a/.specify/scripts/bash/check-prerequisites.sh b/.specify/scripts/bash/check-prerequisites.sh index d5e9c06..3572ca0 100755 --- a/.specify/scripts/bash/check-prerequisites.sh +++ b/.specify/scripts/bash/check-prerequisites.sh @@ -2,7 +2,8 @@ set -euo pipefail -SPECIFY_SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) +SPECIFY_SCRIPT_DIR=$(unset CDPATH; cd -- "$(dirname -- "$0")" && pwd -P) +# shellcheck disable=SC1091 . "${SPECIFY_SCRIPT_DIR}/common.sh" json=false @@ -86,4 +87,3 @@ else printf 'AVAILABLE_DOCS:\n' printf '%s\n' "${docs}" | tr ',' '\n' | sed 's/^/ /; s/"//g' fi - diff --git a/.specify/scripts/bash/common.sh b/.specify/scripts/bash/common.sh index f5e6f41..9dc5987 100755 --- a/.specify/scripts/bash/common.sh +++ b/.specify/scripts/bash/common.sh @@ -3,7 +3,7 @@ set -euo pipefail if [ -z "${SPECIFY_SCRIPT_DIR:-}" ]; then - SPECIFY_SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) + SPECIFY_SCRIPT_DIR=$(unset CDPATH; cd -- "$(dirname -- "$0")" && pwd -P) fi specify_repo_root() { @@ -12,11 +12,12 @@ specify_repo_root() { return 0 fi - CDPATH= cd -- "${SPECIFY_SCRIPT_DIR}/../../.." && pwd -P + (unset CDPATH; cd -- "${SPECIFY_SCRIPT_DIR}/../../.." && pwd -P) } REPO_ROOT=$(specify_repo_root) SPECIFY_DIR="${REPO_ROOT}/.specify" +# shellcheck disable=SC2034 SPECS_DIR="${REPO_ROOT}/specs" specify_has_git() { @@ -118,4 +119,3 @@ specify_paths_json() { "$(specify_json_escape "${plan_file}")" \ "$(specify_json_escape "${tasks_file}")" } - diff --git a/.specify/scripts/bash/create-new-feature.sh b/.specify/scripts/bash/create-new-feature.sh index ec478ae..21dcee7 100755 --- a/.specify/scripts/bash/create-new-feature.sh +++ b/.specify/scripts/bash/create-new-feature.sh @@ -2,7 +2,8 @@ set -euo pipefail -SPECIFY_SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) +SPECIFY_SCRIPT_DIR=$(unset CDPATH; cd -- "$(dirname -- "$0")" && pwd -P) +# shellcheck disable=SC1091 . "${SPECIFY_SCRIPT_DIR}/common.sh" json=false @@ -132,4 +133,3 @@ else printf 'BRANCH_NAME: %s\n' "${branch_name}" printf 'SPEC_FILE: %s\n' "${spec_file}" fi - diff --git a/.specify/scripts/bash/setup-plan.sh b/.specify/scripts/bash/setup-plan.sh index 986a8d8..29d72fb 100755 --- a/.specify/scripts/bash/setup-plan.sh +++ b/.specify/scripts/bash/setup-plan.sh @@ -2,7 +2,8 @@ set -euo pipefail -SPECIFY_SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) +SPECIFY_SCRIPT_DIR=$(unset CDPATH; cd -- "$(dirname -- "$0")" && pwd -P) +# shellcheck disable=SC1091 . "${SPECIFY_SCRIPT_DIR}/common.sh" json=false @@ -41,4 +42,3 @@ else printf 'SPECS_DIR: %s\n' "${feature_dir}" printf 'BRANCH: %s\n' "${branch}" fi - diff --git a/.specify/scripts/bash/setup-tasks.sh b/.specify/scripts/bash/setup-tasks.sh index ef67147..1452fcb 100755 --- a/.specify/scripts/bash/setup-tasks.sh +++ b/.specify/scripts/bash/setup-tasks.sh @@ -2,7 +2,8 @@ set -euo pipefail -SPECIFY_SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) +SPECIFY_SCRIPT_DIR=$(unset CDPATH; cd -- "$(dirname -- "$0")" && pwd -P) +# shellcheck disable=SC1091 . "${SPECIFY_SCRIPT_DIR}/common.sh" json=false @@ -42,4 +43,3 @@ else printf 'SPECS_DIR: %s\n' "${feature_dir}" printf 'BRANCH: %s\n' "${branch}" fi - diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e46535..d9fad73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,25 @@ # Changelog -## [0.5.0](https://github.com/ExtraToast/github-workflows/compare/v0.4.0...v0.5.0) (2026-06-10) +## [0.5.0](https://github.com/JorisJonkers-dev/github-workflows/compare/v0.4.0...v0.5.0) (2026-06-10) ### Features -* GitHub Packages npm auth + reusable deploy-config render-drift ([#13](https://github.com/ExtraToast/github-workflows/issues/13)) ([48578c4](https://github.com/ExtraToast/github-workflows/commit/48578c429faa5cc8298126cc97ecd65ddc3d63ba)) +* GitHub Packages npm auth + reusable deploy-config render-drift ([#13](https://github.com/JorisJonkers-dev/github-workflows/issues/13)) ([48578c4](https://github.com/JorisJonkers-dev/github-workflows/commit/48578c429faa5cc8298126cc97ecd65ddc3d63ba)) -## [0.4.0](https://github.com/ExtraToast/github-workflows/compare/v0.3.0...v0.4.0) (2026-06-10) +## [0.4.0](https://github.com/JorisJonkers-dev/github-workflows/compare/v0.3.0...v0.4.0) (2026-06-10) ### Features -* reusable flux-render-validate workflow + composite action (spec 009) ([#11](https://github.com/ExtraToast/github-workflows/issues/11)) ([cae8c61](https://github.com/ExtraToast/github-workflows/commit/cae8c61ee10701ded2509aa38f4a664f3a58049a)) -* reusable platform-config-validate workflow + action ([#10](https://github.com/ExtraToast/github-workflows/issues/10)) ([512033e](https://github.com/ExtraToast/github-workflows/commit/512033e7b4e2fc288243a42120ef2e112d7b98c1)) +* reusable flux-render-validate workflow + composite action (spec 009) ([#11](https://github.com/JorisJonkers-dev/github-workflows/issues/11)) ([cae8c61](https://github.com/JorisJonkers-dev/github-workflows/commit/cae8c61ee10701ded2509aa38f4a664f3a58049a)) +* reusable platform-config-validate workflow + action ([#10](https://github.com/JorisJonkers-dev/github-workflows/issues/10)) ([512033e](https://github.com/JorisJonkers-dev/github-workflows/commit/512033e7b4e2fc288243a42120ef2e112d7b98c1)) -## [0.3.0](https://github.com/ExtraToast/github-workflows/compare/v0.2.0...v0.3.0) (2026-06-09) +## [0.3.0](https://github.com/JorisJonkers-dev/github-workflows/compare/v0.2.0...v0.3.0) (2026-06-09) ### Features -* per-service CRaC sidecar topology + compose system-test action skeleton (round 3) ([#6](https://github.com/ExtraToast/github-workflows/issues/6)) ([76c09b0](https://github.com/ExtraToast/github-workflows/commit/76c09b0069c7a40d028d7e47a2cc5e041ffcdc9a)) -* round 2 reusable workflows + migration guard ([#5](https://github.com/ExtraToast/github-workflows/issues/5)) ([7650398](https://github.com/ExtraToast/github-workflows/commit/7650398d37e9715be5643f2a606595fb9dc1584a)) -* working compose system-test composite action (round 4) ([#7](https://github.com/ExtraToast/github-workflows/issues/7)) ([c7e593f](https://github.com/ExtraToast/github-workflows/commit/c7e593f9b5365cface340ae1eb1429f68e492c26)) +* per-service CRaC sidecar topology + compose system-test action skeleton (round 3) ([#6](https://github.com/JorisJonkers-dev/github-workflows/issues/6)) ([76c09b0](https://github.com/JorisJonkers-dev/github-workflows/commit/76c09b0069c7a40d028d7e47a2cc5e041ffcdc9a)) +* round 2 reusable workflows + migration guard ([#5](https://github.com/JorisJonkers-dev/github-workflows/issues/5)) ([7650398](https://github.com/JorisJonkers-dev/github-workflows/commit/7650398d37e9715be5643f2a606595fb9dc1584a)) +* working compose system-test composite action (round 4) ([#7](https://github.com/JorisJonkers-dev/github-workflows/issues/7)) ([c7e593f](https://github.com/JorisJonkers-dev/github-workflows/commit/c7e593f9b5365cface340ae1eb1429f68e492c26)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6d0ba3f..4c1678c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -# Contributing (ExtraToast conventions) +# Contributing (JorisJonkers-dev conventions) -These conventions are identical across every ExtraToast repo. This repo is the +These conventions are identical across every JorisJonkers-dev repo. This repo is the template; new repos are bootstrapped from it (see `docs/REPO_SETUP.md`). ## Branch & PR flow diff --git a/LICENSE b/LICENSE index ddeb1f3..8b4a705 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2026 extratoast. All Rights Reserved. +Copyright (c) 2026 jorisjonkers-dev. All Rights Reserved. This software and associated documentation files (the "Software") are the proprietary and confidential property of the copyright holder. diff --git a/README.md b/README.md index 7673601..443dbb2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # github-workflows -Reusable ExtraToast composite actions and workflows live here. Consumer +Reusable JorisJonkers-dev composite actions and workflows live here. Consumer repositories should call them with immutable release tags, not branches. Renovate keeps those pins current. @@ -14,7 +14,7 @@ a repository-provided dev DNS setup script. ```yaml steps: - uses: actions/checkout@v4 - - uses: ExtraToast/github-workflows/actions/prepare-ci-host@v0.2.0 + - uses: JorisJonkers-dev/github-workflows/actions/prepare-ci-host@v0.6.0 with: artifact-pattern: image-* artifact-path: /tmp/images @@ -42,7 +42,7 @@ Installs Java and configures Gradle dependency caching. ```yaml steps: - uses: actions/checkout@v4 - - uses: ExtraToast/github-workflows/actions/setup-java-gradle@v0.2.0 + - uses: JorisJonkers-dev/github-workflows/actions/setup-java-gradle@v0.6.0 with: java-version: '21' java-distribution: temurin @@ -63,12 +63,12 @@ Inputs: ### `setup-node` Installs Node, configures package-manager caching, and installs dependencies. -The package manager may be `pnpm` or Yarn Berry. +The package manager may be npm, pnpm, or Yarn Berry. ```yaml steps: - uses: actions/checkout@v4 - - uses: ExtraToast/github-workflows/actions/setup-node@v0.2.0 + - uses: JorisJonkers-dev/github-workflows/actions/setup-node@v0.6.0 with: node-version: '24' package-manager: pnpm @@ -81,7 +81,7 @@ Yarn example: ```yaml steps: - uses: actions/checkout@v4 - - uses: ExtraToast/github-workflows/actions/setup-node@v0.2.0 + - uses: JorisJonkers-dev/github-workflows/actions/setup-node@v0.6.0 with: node-version: '24' package-manager: yarn @@ -94,23 +94,23 @@ Inputs: | Name | Default | Purpose | | --- | --- | --- | | `node-version` | `24` | Node.js version installed by `actions/setup-node`. | -| `package-manager` | `pnpm` | Package manager to configure. Supported values: `pnpm`, `yarn`. | +| `package-manager` | `pnpm` | Package manager to configure. Supported values: `npm`, `pnpm`, `yarn`. | | `cache-dependency-path` | empty | Lockfile path or paths used for dependency caching. | | `working-directory` | `.` | Directory where dependencies are installed. | | `install-command` | empty | Overrides the install command. Empty uses `pnpm install --frozen-lockfile` or `yarn install --immutable`. | | `github-packages-token` | empty | GitHub Packages token used to write project `.npmrc` auth and export `NODE_AUTH_TOKEN`. | -| `npm-scope` | `@extratoast` | npm scope resolved from GitHub Packages when `github-packages-token` is set. | +| `npm-scope` | `@jorisjonkers-dev` | npm scope resolved from GitHub Packages when `github-packages-token` is set. | | `github-packages-registry` | `https://npm.pkg.github.com` | npm registry URL used for the configured GitHub Packages scope. | ### `platform-config-validate` -Installs a pinned `@extratoast/deploy-config-schema` package, validates caller +Installs a pinned `@jorisjonkers-dev/deploy-config-schema` package, validates caller YAML configs, and can run `render-tree --check` to catch rendered-tree drift. ```yaml steps: - uses: actions/checkout@v6 - - uses: ExtraToast/github-workflows/actions/platform-config-validate@v0.5.0 + - uses: JorisJonkers-dev/github-workflows/actions/platform-config-validate@v0.6.0 with: config-paths: |- platform/**/*.yaml @@ -126,7 +126,7 @@ Inputs: | --- | --- | --- | | `config-paths` | `platform/**/*.yaml`, `platform/**/*.yml` | Newline- or comma-separated file globs to validate. | | `schema-kind` | `auto` | Schema kind: `platform`, `deploy-config`, `service-intent`, `fleet-inventory`, `vault-dynamic-secrets`, or `auto`. | -| `package-version` | `0.3.0` | Version of `@extratoast/deploy-config-schema` to install. | +| `package-version` | `0.3.0` | Version of `@jorisjonkers-dev/deploy-config-schema` to install. | | `drift-check` | `false` | Runs `render-tree --check` after validation when set to `true`. | | `working-directory` | `.` | Directory where config globs are evaluated. | @@ -140,7 +140,7 @@ migration assertions, and hook commands stay in the consumer repository. ```yaml steps: - uses: actions/checkout@v6 - - uses: ExtraToast/github-workflows/actions/compose-system-test-stack@v0.4.0 + - uses: JorisJonkers-dev/github-workflows/actions/compose-system-test-stack@v0.6.0 with: compose-files: |- docker-compose.yml @@ -181,6 +181,93 @@ Inputs: ## Reusable workflows +### `node-ci.yml` + +Runs dependency install plus optional package, lint, typecheck, test, and build +commands for Node repositories. + +```yaml +jobs: + node-ci: + uses: JorisJonkers-dev/github-workflows/.github/workflows/node-ci.yml@v0.6.0 + with: + package-manager: pnpm + lint-command: pnpm lint + typecheck-command: pnpm typecheck + test-command: pnpm test + build-command: pnpm build + secrets: + packages-token: ${{ secrets.GITHUB_TOKEN }} +``` + +### `python-ci.yml` + +Runs standard Python install, lint, and test commands. Each command can be +overridden or disabled with an empty string. + +```yaml +jobs: + python-ci: + uses: JorisJonkers-dev/github-workflows/.github/workflows/python-ci.yml@v0.6.0 +``` + +### `nix-ci.yml` + +Installs Nix and runs a flake check plus an optional validation command. + +```yaml +jobs: + nix-ci: + uses: JorisJonkers-dev/github-workflows/.github/workflows/nix-ci.yml@v0.6.0 +``` + +### `docker-image-ci.yml` + +Builds a Docker image without publishing it. + +```yaml +jobs: + image-ci: + uses: JorisJonkers-dev/github-workflows/.github/workflows/docker-image-ci.yml@v0.6.0 + with: + image-name: example-api + context: . + dockerfile: services/example-api/Dockerfile +``` + +### `container-publish.yml` + +Builds and publishes a GHCR image tagged only with the release version and +`sha-${GITHUB_SHA}`. + +```yaml +jobs: + publish: + uses: JorisJonkers-dev/github-workflows/.github/workflows/container-publish.yml@v0.6.0 + with: + image-name: example-api + version: ${{ needs.release.outputs.version }} +``` + +### `gitops-ci.yml` + +Runs platform config validation, Flux render validation, optional deploy-config +render drift, and optional caller-owned system tests. + +```yaml +jobs: + gitops-ci: + uses: JorisJonkers-dev/github-workflows/.github/workflows/gitops-ci.yml@v0.6.0 + with: + overlay-paths: |- + clusters/production + platform-config-paths: |- + inventory/**/*.yaml + inventory/**/*.yml + secrets: + packages-token: ${{ secrets.GITHUB_TOKEN }} +``` + ### `platform-config-validate.yml` Validates platform YAML from any consumer repository with one reusable workflow @@ -190,7 +277,7 @@ standard validation job. ```yaml jobs: platform-config: - uses: ExtraToast/github-workflows/.github/workflows/platform-config-validate.yml@v0.5.0 + uses: JorisJonkers-dev/github-workflows/.github/workflows/platform-config-validate.yml@v0.6.0 with: config-paths: |- platform/**/*.yaml @@ -206,7 +293,7 @@ Inputs: | --- | --- | --- | | `config-paths` | `platform/**/*.yaml`, `platform/**/*.yml` | Newline- or comma-separated file globs to validate. | | `schema-kind` | `auto` | Schema kind: `platform`, `deploy-config`, `service-intent`, `fleet-inventory`, `vault-dynamic-secrets`, or `auto`. | -| `package-version` | `0.3.0` | Version of `@extratoast/deploy-config-schema` to install. | +| `package-version` | `0.3.0` | Version of `@jorisjonkers-dev/deploy-config-schema` to install. | | `drift-check` | `false` | Runs `render-tree --check` after validation when set to `true`. | | `working-directory` | `.` | Directory where config globs are evaluated. | @@ -219,7 +306,7 @@ greater than the base branch maximum for the same service. ```yaml jobs: migration-guard: - uses: ExtraToast/github-workflows/.github/workflows/migration-guard.yml@v0.3.0 + uses: JorisJonkers-dev/github-workflows/.github/workflows/migration-guard.yml@v0.6.0 with: migration-regex: 'services/[^/]+/src/main/resources/db/migration(-pg)?/V[0-9][^/]*\.sql$' scope-regex: '(services/[^/]+)/.*' @@ -246,7 +333,7 @@ sidecars. ```yaml jobs: crac-train: - uses: ExtraToast/github-workflows/.github/workflows/crac-train.yml@v0.3.0 + uses: JorisJonkers-dev/github-workflows/.github/workflows/crac-train.yml@v0.6.0 with: service-matrix: >- [ @@ -310,7 +397,7 @@ assertions, and mutation behavior stay in the caller repository. ```yaml jobs: production-canary: - uses: ExtraToast/github-workflows/.github/workflows/production-canary.yml@v0.3.0 + uses: JorisJonkers-dev/github-workflows/.github/workflows/production-canary.yml@v0.6.0 with: enabled: ${{ vars.PROD_CANARY_ENABLED == 'true' }} post-push-delay-seconds: 180 @@ -342,7 +429,7 @@ Runs generic Gradle lint and test jobs for JVM repositories. ```yaml jobs: jvm-ci: - uses: ExtraToast/github-workflows/.github/workflows/jvm-ci.yml@v0.2.0 + uses: JorisJonkers-dev/github-workflows/.github/workflows/jvm-ci.yml@v0.6.0 with: java-version: '21' gradle-args: --no-daemon --stacktrace diff --git a/VERSIONING.md b/VERSIONING.md index 25aadc4..df907e3 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -1,6 +1,6 @@ # Versioning & release -Every ExtraToast repo is versioned and released the same way. Nothing resolves +Every JorisJonkers-dev repo is versioned and released the same way. Nothing resolves or deploys from a moving branch — `main` is an integration branch, not a deploy target. @@ -11,12 +11,12 @@ deploy target. 2. `release.yml` (release-please) maintains a release PR. Merging it tags `vX.Y.Z`, writes `CHANGELOG.md`, and bumps `.release-please-manifest.json`. 3. The published-release event publishes artifacts at that exact version: - - Maven libraries/plugins → GitHub Packages under `dev.extratoast.*` - - npm packages → GitHub Packages under `@extratoast/*` - - container images → `ghcr.io/extratoast//:X.Y.Z` + - Maven libraries/plugins → GitHub Packages under `dev.jorisjonkers.*` + - npm packages → GitHub Packages under `@jorisjonkers-dev/*` + - container images → `ghcr.io/jorisjonkers-dev//:X.Y.Z` SemVer: pre-1.0 (`0.y.z`) treats minor as the breaking lever -(`bump-minor-pre-major`). Promote to `1.0.0` once an artifact's API is stable. +(`bump-minor-pre-major`). Promote to `1.6.0` once an artifact's API is stable. ## Consuming shared artifacts (exact pins, no ranges) @@ -24,15 +24,15 @@ SemVer: pre-1.0 (`0.y.z`) treats minor as the breaking lever them via the catalog. Example: ```toml [versions] - extratoast-kotlin-commons = "0.3.1" + jorisjonkers-kotlin-commons = "0.3.1" [libraries] - extratoast-command = { module = "dev.extratoast.kotlin-commons:command", version.ref = "extratoast-kotlin-commons" } + jorisjonkers-command = { module = "dev.jorisjonkers.kotlin-commons:command", version.ref = "jorisjonkers-kotlin-commons" } ``` - **npm**: pin exact versions in the manifest (no `^`/`~`). - **GitHub Actions / reusable workflows**: pin to a release tag (and digest via - Renovate), e.g. `uses: ExtraToast/github-workflows/.github/workflows/jvm-ci.yml@v1.2.0`. + Renovate), e.g. `uses: JorisJonkers-dev/github-workflows/.github/workflows/jvm-ci.yml@v0.6.0`. -[Renovate](renovate.json) opens exact-version bump PRs (ExtraToast artifacts +[Renovate](renovate.json) opens exact-version bump PRs (JorisJonkers-dev artifacts grouped into one platform bump). Every bump PR must pass `Pipeline Complete` before merge. diff --git a/actions/deploy-config-render-drift/action.yml b/actions/deploy-config-render-drift/action.yml index e53dd8d..1392215 100644 --- a/actions/deploy-config-render-drift/action.yml +++ b/actions/deploy-config-render-drift/action.yml @@ -3,7 +3,7 @@ description: Render deploy-config-schema adapter outputs and compare them with c inputs: package-version: - description: Version of @extratoast/deploy-config-schema to install. + description: Version of @jorisjonkers-dev/deploy-config-schema to install. required: false default: ^0.6.0 deploy-config-command: @@ -17,7 +17,7 @@ inputs: required: false default: . node-auth-token: - description: Token with packages:read for installing @extratoast packages from GitHub Packages (pass secrets.GITHUB_TOKEN). + description: Token with packages:read for installing @jorisjonkers-dev packages from GitHub Packages (pass secrets.GITHUB_TOKEN). required: false default: "" diff --git a/actions/deploy-config-render-drift/run.sh b/actions/deploy-config-render-drift/run.sh index b35f459..1447007 100644 --- a/actions/deploy-config-render-drift/run.sh +++ b/actions/deploy-config-render-drift/run.sh @@ -22,18 +22,18 @@ install_schema_cli() { rm -rf "$install_root" mkdir -p "$install_root" { - printf '%s\n' '@extratoast:registry=https://npm.pkg.github.com' + printf '%s\n' '@jorisjonkers-dev:registry=https://npm.pkg.github.com' if [ -n "${NODE_AUTH_TOKEN:-}" ]; then printf '%s\n' "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" fi printf '%s\n' 'always-auth=true' } > "${npmrc}" - echo "::group::Install @extratoast/deploy-config-schema@${version}" >&2 + echo "::group::Install @jorisjonkers-dev/deploy-config-schema@${version}" >&2 ( cd "${install_root}" npm init -y >/dev/null - npm install --userconfig "${npmrc}" --no-audit --no-fund --save-exact "@extratoast/deploy-config-schema@${version}" >&2 + npm install --userconfig "${npmrc}" --no-audit --no-fund --save-exact "@jorisjonkers-dev/deploy-config-schema@${version}" >&2 ) echo "::endgroup::" >&2 @@ -41,7 +41,7 @@ install_schema_cli() { cd "${install_root}" node - <<'NODE' const path = require("path"); -const packageRoot = path.resolve("node_modules/@extratoast/deploy-config-schema"); +const packageRoot = path.resolve("node_modules/@jorisjonkers-dev/deploy-config-schema"); const manifest = require(path.join(packageRoot, "package.json")); const bin = manifest.bin; @@ -53,7 +53,7 @@ if (typeof bin === "string") { } if (!relativeBin) { - console.error("Package @extratoast/deploy-config-schema does not declare a CLI bin."); + console.error("Package @jorisjonkers-dev/deploy-config-schema does not declare a CLI bin."); process.exit(1); } @@ -138,7 +138,7 @@ main() { local render_root="${temp_root}/rendered" mkdir -p "${render_root}" - export DEPLOY_CONFIG_SCHEMA_LOCAL="${install_root}/node_modules/@extratoast/deploy-config-schema" + export DEPLOY_CONFIG_SCHEMA_LOCAL="${install_root}/node_modules/@jorisjonkers-dev/deploy-config-schema" export DEPLOY_CONFIG_OUT="${temp_root}/deploy-config.json" export PATH="${install_root}/node_modules/.bin:${PATH}" diff --git a/actions/flux-render-validate/action.yml b/actions/flux-render-validate/action.yml index 59229d6..610df23 100644 --- a/actions/flux-render-validate/action.yml +++ b/actions/flux-render-validate/action.yml @@ -12,7 +12,7 @@ inputs: crd-catalog-source: description: Repository containing scripts/validate-flux-render.sh and schemas/crds. required: false - default: ExtraToast/platform-blueprints + default: JorisJonkers-dev/platform-blueprints crd-catalog-ref: description: Git ref for crd-catalog-source. required: false diff --git a/actions/platform-config-validate/action.yml b/actions/platform-config-validate/action.yml index 21160e8..1e5046b 100644 --- a/actions/platform-config-validate/action.yml +++ b/actions/platform-config-validate/action.yml @@ -1,5 +1,5 @@ name: Platform Config Validate -description: Validate platform YAML with @extratoast/deploy-config-schema and optionally check rendered-tree drift. +description: Validate platform YAML with @jorisjonkers-dev/deploy-config-schema and optionally check rendered-tree drift. inputs: config-paths: @@ -13,11 +13,11 @@ inputs: required: false default: auto package-version: - description: Version of @extratoast/deploy-config-schema to install. + description: Version of @jorisjonkers-dev/deploy-config-schema to install. required: false default: 0.3.0 node-auth-token: - description: Token with packages:read for installing @extratoast packages from GitHub Packages (pass secrets.GITHUB_TOKEN). + description: Token with packages:read for installing @jorisjonkers-dev packages from GitHub Packages (pass secrets.GITHUB_TOKEN). required: false default: "" drift-check: diff --git a/actions/platform-config-validate/run.sh b/actions/platform-config-validate/run.sh index f07f06d..c61fc42 100755 --- a/actions/platform-config-validate/run.sh +++ b/actions/platform-config-validate/run.sh @@ -51,18 +51,18 @@ install_schema_cli() { rm -rf "$install_root" mkdir -p "$install_root" { - printf '%s\n' '@extratoast:registry=https://npm.pkg.github.com' + printf '%s\n' '@jorisjonkers-dev:registry=https://npm.pkg.github.com' if [ -n "${NODE_AUTH_TOKEN:-}" ]; then printf '%s\n' "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" fi printf '%s\n' 'always-auth=true' } > "$npmrc" - echo "::group::Install @extratoast/deploy-config-schema@$version" >&2 + echo "::group::Install @jorisjonkers-dev/deploy-config-schema@$version" >&2 ( cd "$install_root" npm init -y >/dev/null - npm install --userconfig "$npmrc" --no-audit --no-fund --save-exact "@extratoast/deploy-config-schema@$version" >&2 + npm install --userconfig "$npmrc" --no-audit --no-fund --save-exact "@jorisjonkers-dev/deploy-config-schema@$version" >&2 ) echo "::endgroup::" >&2 @@ -70,7 +70,7 @@ install_schema_cli() { cd "$install_root" node - <<'NODE' const path = require("path"); -const packageRoot = path.resolve("node_modules/@extratoast/deploy-config-schema"); +const packageRoot = path.resolve("node_modules/@jorisjonkers-dev/deploy-config-schema"); const manifest = require(path.join(packageRoot, "package.json")); const bin = manifest.bin; @@ -82,7 +82,7 @@ if (typeof bin === "string") { } if (!relativeBin) { - console.error("Package @extratoast/deploy-config-schema does not declare a CLI bin."); + console.error("Package @jorisjonkers-dev/deploy-config-schema does not declare a CLI bin."); process.exit(1); } @@ -109,6 +109,7 @@ expand_config_files() { local -a matches=() # Intentionally unquoted so caller-provided glob patterns expand. + # shellcheck disable=SC2206 matches=( $pattern ) if [ "${#matches[@]}" -eq 0 ] && [ -f "$pattern" ]; then matches=( "$pattern" ) @@ -165,7 +166,7 @@ main() { exit 1 fi - printf 'Validating %d platform config file(s) with @extratoast/deploy-config-schema@%s\n' "${#files[@]}" "$package_version" + printf 'Validating %d platform config file(s) with @jorisjonkers-dev/deploy-config-schema@%s\n' "${#files[@]}" "$package_version" printf 'Schema kind: %s\n' "$schema_kind" printf 'Working directory: %s\n' "$working_directory" printf 'Drift check: %s\n' "$drift_check" diff --git a/actions/setup-node/action.yml b/actions/setup-node/action.yml index b261f27..e8c2394 100644 --- a/actions/setup-node/action.yml +++ b/actions/setup-node/action.yml @@ -7,7 +7,7 @@ inputs: required: false default: '24' package-manager: - description: Package manager to configure. Supported values are pnpm and yarn. + description: Package manager to configure. Supported values are npm, pnpm, and yarn. required: false default: pnpm cache-dependency-path: @@ -29,7 +29,7 @@ inputs: npm-scope: description: npm scope resolved from GitHub Packages when github-packages-token is set. required: false - default: '@extratoast' + default: '@jorisjonkers-dev' github-packages-registry: description: npm registry URL used for the configured GitHub Packages scope. required: false @@ -44,10 +44,10 @@ runs: PACKAGE_MANAGER: ${{ inputs.package-manager }} run: | case "$PACKAGE_MANAGER" in - pnpm|yarn) + npm|pnpm|yarn) ;; *) - echo "::error::Unsupported package-manager: $PACKAGE_MANAGER. Use pnpm or yarn." + echo "::error::Unsupported package-manager: $PACKAGE_MANAGER. Use npm, pnpm, or yarn." exit 1 ;; esac @@ -110,6 +110,9 @@ runs: run: | if [ -z "$INSTALL_COMMAND" ]; then case "$PACKAGE_MANAGER" in + npm) + INSTALL_COMMAND="npm ci" + ;; pnpm) INSTALL_COMMAND="pnpm install --frozen-lockfile" ;; diff --git a/release-please-config.json b/release-please-config.json index 2fce4ad..63d4f1d 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,5 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "bootstrap-sha": "1eef0fe38c718b8263edb46b0bc4e2f1c6eb30a1", "release-type": "simple", "packages": { ".": { diff --git a/renovate.json b/renovate.json index 3ec76d2..f70c126 100644 --- a/renovate.json +++ b/renovate.json @@ -1,26 +1,4 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended", - ":semanticCommits", - ":dependencyDashboard" - ], - "rangeStrategy": "pin", - "labels": ["dependencies"], - "minimumReleaseAge": "3 days", - "packageRules": [ - { - "description": "Group all ExtraToast shared artifacts so a coherent platform bump lands in one PR.", - "matchPackagePatterns": ["^dev\\.extratoast", "^@extratoast/"], - "matchDepNames": ["ExtraToast/github-workflows"], - "groupName": "extratoast shared artifacts", - "labels": ["dependencies", "extratoast-platform"] - }, - { - "description": "Pin GitHub Actions to immutable refs.", - "matchManagers": ["github-actions"], - "pinDigests": true - } - ], - "lockFileMaintenance": { "enabled": true } + "extends": ["github>JorisJonkers-dev/renovate-config"] } diff --git a/scripts/__pycache__/check_migrations.cpython-311.pyc b/scripts/__pycache__/check_migrations.cpython-311.pyc deleted file mode 100644 index 6bf3913..0000000 Binary files a/scripts/__pycache__/check_migrations.cpython-311.pyc and /dev/null differ diff --git a/scripts/apply-ruleset.sh b/scripts/apply-ruleset.sh index 48950b2..3f2f2e0 100755 --- a/scripts/apply-ruleset.sh +++ b/scripts/apply-ruleset.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Apply the org-standard branch ruleset (.github/rulesets/main.json) to a repo. # -# Every ExtraToast repo must carry the common ruleset that makes the single +# Every JorisJonkers-dev repo must carry the common ruleset that makes the single # "Pipeline Complete" status check required before any PR can merge. This # script is idempotent: it creates the "Main" ruleset if absent, otherwise # updates the existing one in place. diff --git a/tests/__pycache__/test_check_migrations.cpython-311.pyc b/tests/__pycache__/test_check_migrations.cpython-311.pyc deleted file mode 100644 index 9183635..0000000 Binary files a/tests/__pycache__/test_check_migrations.cpython-311.pyc and /dev/null differ diff --git a/tests/test_crac_train_workflow.py b/tests/test_crac_train_workflow.py index d5331d5..962cc2c 100644 --- a/tests/test_crac_train_workflow.py +++ b/tests/test_crac_train_workflow.py @@ -1,5 +1,6 @@ from __future__ import annotations +import json import os import re import subprocess @@ -14,6 +15,12 @@ CRAC_WORKFLOW = ROOT / ".github/workflows/crac-train.yml" CI_WORKFLOW = ROOT / ".github/workflows/ci.yml" PLATFORM_CONFIG_WORKFLOW = ROOT / ".github/workflows/platform-config-validate.yml" +NODE_CI_WORKFLOW = ROOT / ".github/workflows/node-ci.yml" +PYTHON_CI_WORKFLOW = ROOT / ".github/workflows/python-ci.yml" +NIX_CI_WORKFLOW = ROOT / ".github/workflows/nix-ci.yml" +DOCKER_IMAGE_CI_WORKFLOW = ROOT / ".github/workflows/docker-image-ci.yml" +CONTAINER_PUBLISH_WORKFLOW = ROOT / ".github/workflows/container-publish.yml" +GITOPS_CI_WORKFLOW = ROOT / ".github/workflows/gitops-ci.yml" COMPOSE_ACTION = ROOT / "actions/compose-system-test-stack/action.yml" COMPOSE_RUNNER = ROOT / "actions/compose-system-test-stack/run.sh" COMPOSE_ROUTES_FIXTURE = ROOT / "actions/compose-system-test-stack/fixtures/routes.example.txt" @@ -22,6 +29,9 @@ PLATFORM_CONFIG_RUNNER = ROOT / "actions/platform-config-validate/run.sh" PLATFORM_CONFIG_PLATFORM_FIXTURE = ROOT / "actions/platform-config-validate/fixtures/platform.example.yml" PLATFORM_CONFIG_SERVICE_FIXTURE = ROOT / "actions/platform-config-validate/fixtures/service-intent.example.yml" +SETUP_NODE_ACTION = ROOT / "actions/setup-node/action.yml" +RENOVATE_CONFIG = ROOT / "renovate.json" +RELEASE_CONFIG = ROOT / "release-please-config.json" README = ROOT / "README.md" @@ -348,7 +358,7 @@ def install_fake_npm(self, bin_dir: Path) -> None: printf '{}\\n' > package.json ;; install) - package_dir="node_modules/@extratoast/deploy-config-schema" + package_dir="node_modules/@jorisjonkers-dev/deploy-config-schema" mkdir -p "$package_dir" cat > "$package_dir/package.json" <<'JSON' {"bin":{"deploy-config-schema":"cli.js"}} @@ -424,7 +434,7 @@ def test_reusable_workflow_exposes_expected_inputs_and_wraps_action(self) -> Non self.assertIn("on:\n workflow_call:", self.workflow) self.assertIn("uses: ./.github-workflows/actions/platform-config-validate", self.workflow) - self.assertIn("repository: ExtraToast/github-workflows", self.workflow) + self.assertIn("repository: JorisJonkers-dev/github-workflows", self.workflow) self.assertIn("actions/setup-node@v6", self.action) self.assertIn('run: bash "${{ github.action_path }}/run.sh"', self.action) @@ -460,7 +470,7 @@ def test_runner_expands_globs_installs_package_and_runs_drift_check(self) -> Non self.assertEqual(result.returncode, 0, result.stderr) log = (workdir / "commands.log").read_text(encoding="utf-8") self.assertIn("npm <--userconfig>", log) - self.assertIn("<--no-audit> <--no-fund> <--save-exact> <@extratoast/deploy-config-schema@9.8.7>", log) + self.assertIn("<--no-audit> <--no-fund> <--save-exact> <@jorisjonkers-dev/deploy-config-schema@9.8.7>", log) self.assertIn( "cli ", log, @@ -494,8 +504,8 @@ def test_generic_fixtures_and_readme_usage_are_present(self) -> None: self.assertIn("name: example-platform", platform_fixture) self.assertIn("api-service:", service_fixture) self.assertIn("platform-config-validate.yml", self.readme) - self.assertIn("ExtraToast/github-workflows/.github/workflows/platform-config-validate.yml", self.readme) - self.assertIn("@extratoast/deploy-config-schema", self.readme) + self.assertIn("JorisJonkers-dev/github-workflows/.github/workflows/platform-config-validate.yml", self.readme) + self.assertIn("@jorisjonkers-dev/deploy-config-schema", self.readme) def test_ci_uses_official_actionlint_download_script(self) -> None: self.assertIn("download-actionlint.bash", self.ci) @@ -503,5 +513,90 @@ def test_ci_uses_official_actionlint_download_script(self) -> None: self.assertNotIn("rhysd/actionlint@v1", self.ci) +class MigrationReusableWorkflowSurfaceTest(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.node_ci = NODE_CI_WORKFLOW.read_text(encoding="utf-8") + cls.python_ci = PYTHON_CI_WORKFLOW.read_text(encoding="utf-8") + cls.nix_ci = NIX_CI_WORKFLOW.read_text(encoding="utf-8") + cls.docker_image_ci = DOCKER_IMAGE_CI_WORKFLOW.read_text(encoding="utf-8") + cls.container_publish = CONTAINER_PUBLISH_WORKFLOW.read_text(encoding="utf-8") + cls.gitops_ci = GITOPS_CI_WORKFLOW.read_text(encoding="utf-8") + cls.setup_node = SETUP_NODE_ACTION.read_text(encoding="utf-8") + cls.readme = README.read_text(encoding="utf-8") + + def test_new_reusable_workflows_are_documented_at_v0_6_0(self) -> None: + for workflow in [ + "node-ci.yml", + "python-ci.yml", + "nix-ci.yml", + "docker-image-ci.yml", + "container-publish.yml", + "gitops-ci.yml", + ]: + self.assertTrue((ROOT / f".github/workflows/{workflow}").is_file()) + self.assertIn( + f"JorisJonkers-dev/github-workflows/.github/workflows/{workflow}@v0.6.0", + self.readme, + ) + + def test_node_ci_uses_setup_node_and_setup_node_supports_npm(self) -> None: + for expected_input in [ + "node-version", + "package-manager", + "working-directory", + "install-command", + "lint-command", + "typecheck-command", + "test-command", + "build-command", + "package-check-command", + ]: + self.assertIn(f" {expected_input}:", self.node_ci) + + self.assertIn("uses: ./.github-workflows/actions/setup-node", self.node_ci) + self.assertIn("repository: JorisJonkers-dev/github-workflows", self.node_ci) + self.assertIn("npm|pnpm|yarn)", self.setup_node) + self.assertIn('INSTALL_COMMAND="npm ci"', self.setup_node) + self.assertIn("default: '@jorisjonkers-dev'", self.setup_node) + + def test_language_and_build_reusables_expose_expected_commands(self) -> None: + self.assertIn("default: python -m pip install -r requirements-dev.txt", self.python_ci) + self.assertIn("default: ruff check .", self.python_ci) + self.assertIn("default: python -m unittest discover", self.python_ci) + self.assertIn("uses: cachix/install-nix-action@v31", self.nix_ci) + self.assertIn("default: nix flake check --print-build-logs", self.nix_ci) + self.assertIn("uses: docker/build-push-action@v7", self.docker_image_ci) + self.assertIn("push: false", self.docker_image_ci) + + def test_container_publish_tags_version_and_sha_only(self) -> None: + self.assertIn("packages: write", self.container_publish) + self.assertIn("uses: docker/login-action@v3", self.container_publish) + self.assertIn('printf \'%s:%s\\n\' "$image_ref" "$VERSION"', self.container_publish) + self.assertIn('printf \'%s:sha-%s\\n\' "$image_ref" "$GITHUB_SHA"', self.container_publish) + self.assertNotIn(":latest", self.container_publish) + + def test_gitops_ci_runs_required_and_optional_validation_steps(self) -> None: + self.assertIn("uses: ./.github-workflows/actions/platform-config-validate", self.gitops_ci) + self.assertIn("uses: ./.github-workflows/actions/flux-render-validate", self.gitops_ci) + self.assertIn("uses: ./.github-workflows/actions/deploy-config-render-drift", self.gitops_ci) + self.assertIn("inputs.deploy-config-command != '' && inputs.deploy-config-targets != ''", self.gitops_ci) + self.assertIn("inputs.system-tests-command != ''", self.gitops_ci) + + def test_release_and_renovate_configs_match_migration_contract(self) -> None: + renovate = json.loads(RENOVATE_CONFIG.read_text(encoding="utf-8")) + release = json.loads(RELEASE_CONFIG.read_text(encoding="utf-8")) + + self.assertEqual( + renovate, + { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["github>JorisJonkers-dev/renovate-config"], + }, + ) + self.assertEqual(release["bootstrap-sha"], "1eef0fe38c718b8263edb46b0bc4e2f1c6eb30a1") + self.assertEqual(release["release-type"], "simple") + + if __name__ == "__main__": unittest.main()