diff --git a/tasks/docker-registry/task.yaml b/tasks/docker-registry/task.yaml index 7cf2a12..0cceb0b 100644 --- a/tasks/docker-registry/task.yaml +++ b/tasks/docker-registry/task.yaml @@ -6,79 +6,53 @@ spec: params: - name: subdirectory type: string - description: Subdirectory within the repo where the source code is located default: "" + description: Subdirectory within the repo where the source code is located - name: imageName - description: Base image name with registry (e.g. docker.unbox-x.net/registry/unbox-x-aisi-cron-app) type: string + description: Base image name with registry (e.g. docker.unbox-x.net/registry/unbox-x-aisi-cron-app) - name: tag - description: Version tag to apply to the image (e.g. v0.2.0) type: string + description: Version tag to apply to the image (e.g. v0.2.0) - name: dockerfile - description: Path to Dockerfile type: string default: ./Dockerfile + description: Path to Dockerfile - name: context - description: Build context path (relative to subdirectory) type: string default: . - - - name: kanikoArgs - description: arguments for kaniko - type: string - default: "" + description: Build context path (relative to subdirectory) workspaces: - name: source description: Source code workspace - - - name: docker-auth - description: Docker registry credentials (username + password) + - name: docker-dot-credentials + description: Workspace containing config.json (as Secret) results: - name: imageUrl description: Final pushed image URL with tag (e.g. registry/app:v0.2.0) steps: - - name: write-docker-config + - name: prepare-docker-auth image: alpine:3.21.3 - workingDir: /workspace/source + workingDir: /workspace/source/$(params.subdirectory) script: | #!/bin/sh set -e - if [ -n "$(params.subdirectory)" ]; then - cd "$(params.subdirectory)" - fi - - echo "πŸ“¦ UkanikoArgs: $(params.kanikoArgs)" - + echo "πŸ” Copying docker .dockerconfigjson to /tekton/home/.docker" + mkdir -p /tekton/home/.docker + cp /workspace/docker-dot-credentials/.dockerconfigjson /tekton/home/.docker/config.json IMAGE="$(params.imageName):$(params.tag)" - USERNAME=$(cat /workspace/docker-auth/username) - PASSWORD=$(cat /workspace/docker-auth/password) - REGISTRY=$(echo "$IMAGE" | cut -d/ -f1) - AUTH=$(echo -n "$USERNAME:$PASSWORD" | base64) - echo "πŸ“¦ Using image: $IMAGE" echo -n "$IMAGE" > /tekton/results/imageUrl - echo "πŸ” Writing Docker config for $REGISTRY..." - mkdir -p /tekton/home/.docker - cat < /tekton/home/.docker/config.json - { - "auths": { - "$REGISTRY": { - "auth": "$AUTH" - } - } - } - EOF - - name: kaniko-build image: gcr.io/kaniko-project/executor:v1.23.2 workingDir: $(workspaces.source.path)/$(params.subdirectory) @@ -94,3 +68,8 @@ spec: - --skip-tls-verify - --verbosity=info - --reproducible + {{- if $(params.kanikoArgs) }} + {{- range $arg := splitList " " "$(params.kanikoArgs)" }} + - {{ $arg }} + {{- end }} + {{- end }} diff --git a/tasks/nodejs-nx-analysis/task.yaml b/tasks/nodejs-nx-analysis/task.yaml index 2de709c..3f89285 100644 --- a/tasks/nodejs-nx-analysis/task.yaml +++ b/tasks/nodejs-nx-analysis/task.yaml @@ -1,4 +1,3 @@ ---- apiVersion: tekton.dev/v1 kind: Task metadata: @@ -22,13 +21,6 @@ spec: workspaces: - name: source description: Git-cloned source code with Nx monorepo - - name: npm-auth - optional: true - description: | - A workspace containing authentication credentials for a private npm repository. - Should include: - - username - - password results: - name: coverage-dir @@ -39,27 +31,17 @@ spec: steps: - name: lint-and-test image: $(params.nodejsImageName) - workingDir: /workspace/source + workingDir: /workspace/source/$(params.subdirectory) script: | #!/usr/bin/env bash set -e export NX_SOCKET_DIR=/tmp/nx-socket - if [ -n "$(params.subdirectory)" ]; then - cd "$(params.subdirectory)" - fi - echo "🧩 Using pnpm via corepack" corepack enable corepack prepare pnpm@8.15.4 --activate - echo "πŸ” Checking for private npm credentials" - if [ -f /workspace/npm-auth/.npmrc ]; then - echo "βœ… Found .npmrc" - cp /workspace/npm-auth/.npmrc ~/.npmrc - fi - echo "πŸ“¦ Installing dependencies with pnpm" pnpm install --frozen-lockfile diff --git a/tasks/pybuild/task.yaml b/tasks/pybuild/task.yaml index a55c523..36aca14 100644 --- a/tasks/pybuild/task.yaml +++ b/tasks/pybuild/task.yaml @@ -6,104 +6,69 @@ spec: params: - name: subdirectory type: string - description: Subdirectory within the repo where the source code is located default: "" + description: Subdirectory within the repo where the source code is located - name: pythonImageName type: string - description: Python version to use (e.g., 3.9, 3.11) default: "python:3.11-slim" - - - name: pypi-username - type: string - description: PyPI username (fallback) - default: "" - - - name: pypi-password - type: string - description: PyPI password or token (fallback) - default: "" + description: Python version to use workspaces: - name: source - description: Workspace containing the cloned Git repository from git-clone-checkout - - - name: pypi-auth - optional: true - description: | - A workspace containing authentication credentials for a private PyPI repository. - Should include: - - username - - password + description: Workspace containing the cloned Git repository results: - name: build-artifact-path description: Path to the built artifact directory (e.g., dist/) steps: - - name: install-dependencies + - name: build-package image: $(params.pythonImageName) - workingDir: /workspace/source + workingDir: /workspace/source/$(params.subdirectory) + env: + - name: HOME + value: /workspace/source/$(params.subdirectory)/___HOME___ script: | #!/usr/bin/env bash set -e - if [ -n "$(params.subdirectory)" ]; then - cd "$(params.subdirectory)" - fi - - PYPI_USER="$(params.pypi-username)" - PYPI_PASS="$(params.pypi-password)" - - if [ -f /workspace/pypi-auth/username ]; then - PYPI_USER=$(cat /workspace/pypi-auth/username) - fi - if [ -f /workspace/pypi-auth/password ]; then - PYPI_PASS=$(cat /workspace/pypi-auth/password) - fi - - echo "πŸ”§ Installing dependencies..." + echo "πŸ”§ Installing base tools..." pip install --upgrade pip --root-user-action=ignore + # Poetry ν”„λ‘œμ νŠΈ 처리 if [ -f pyproject.toml ]; then echo "[INFO] Poetry project detected" - pip install poetry tomli --root-user-action=ignore + pip install poetry --root-user-action=ignore - REPO_NAME=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["name"])') - REPO_URL=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["url"])') + poetry lock --no-update || echo "[WARN] poetry lock skipped" + poetry install --no-root || echo "[WARN] poetry install skipped" - echo "[INFO] Configuring poetry source '$REPO_NAME' β†’ $REPO_URL" - poetry config virtualenvs.in-project true - poetry config repositories."$REPO_NAME" "$REPO_URL" - poetry config http-basic."$REPO_NAME" "$PYPI_USER" "$PYPI_PASS" - - poetry lock --no-cache --regenerate - poetry install - - echo "πŸ“¦ Building package with Poetry..." + echo "πŸ“¦ Building with Poetry..." poetry build - elif [ -f requirements.txt ] && [ -f setup.py ]; then + # setup.py 기반 λΉŒλ“œ + elif [ -f setup.py ] && [ -f requirements.txt ]; then echo "[INFO] setup.py project detected" pip install -r requirements.txt --root-user-action=ignore pip install build --root-user-action=ignore - echo "πŸ“¦ Building package with build module..." + echo "πŸ“¦ Building with Python Build module..." python -m build else - echo "[ERROR] No valid build configuration found (pyproject.toml or setup.py required)" + echo "❌ No valid build configuration found (pyproject.toml or setup.py required)" exit 1 fi - echo "πŸ“‚ Verifying built artifacts..." + echo "πŸ“‚ Checking built artifacts..." BUILD_PATH="/workspace/source/$(params.subdirectory)/dist" echo -n "$BUILD_PATH" > /tekton/results/build-artifact-path - if [ -d "$BUILD_PATH" ] && [ -n "$(ls -A $BUILD_PATH)" ]; then + if [ -d "$BUILD_PATH" ] && [ -n "$(ls -A "$BUILD_PATH")" ]; then echo "βœ… Build artifacts created in $BUILD_PATH:" ls -l "$BUILD_PATH" else - echo "❌ No build artifacts found in $BUILD_PATH" + echo "❌ No artifacts found in $BUILD_PATH" exit 1 fi diff --git a/tasks/pylint/task.yaml b/tasks/pylint/task.yaml index 97b0365..25309db 100644 --- a/tasks/pylint/task.yaml +++ b/tasks/pylint/task.yaml @@ -11,7 +11,7 @@ spec: - name: pythonImageName type: string - description: Python version to use (e.g., 3.9, 3.11) + description: Python version to use (e.g., python:3.11-slim) default: "python:3.11-slim" - name: pylint-args @@ -19,86 +19,72 @@ spec: description: Additional arguments for pylint (e.g., --fail-under=8) default: "" - - name: pypi-username + - name: fail-on-lint type: string - description: PyPI username (fallback) - default: "" + default: "false" + description: | + If true, the step will exit with a failure code if pylint reports issues. + Otherwise, it will always exit 0. - - name: pypi-password - type: string - description: PyPI password or token (fallback) - default: "" + results: + - name: pylint-exit-code + description: Exit code returned by pylint (0=clean, non-zero=issues) workspaces: - name: source - description: Workspace containing the cloned Git repository from git-clone-checkout - - - name: pypi-auth - optional: true - description: | - A workspace containing authentication credentials for a private PyPI repository. - Should include: - - username - - password + description: Workspace containing the cloned Git repository steps: - - name: install-dependencies + - name: run-pylint image: $(params.pythonImageName) - workingDir: /workspace/source + workingDir: /workspace/source/$(params.subdirectory) + env: + - name: HOME + value: /workspace/source/$(params.subdirectory)/___HOME___ script: | #!/usr/bin/env bash set -e - if [ -n "$(params.subdirectory)" ]; then - cd "$(params.subdirectory)" - fi - - PYPI_USER="$(params.pypi-username)" - PYPI_PASS="$(params.pypi-password)" - - if [ -f /workspace/pypi-auth/username ]; then - PYPI_USER=$(cat /workspace/pypi-auth/username) - fi - if [ -f /workspace/pypi-auth/password ]; then - PYPI_PASS=$(cat /workspace/pypi-auth/password) - fi - echo "πŸ”§ Installing dependencies..." pip install --upgrade pip --root-user-action=ignore if [ -f pyproject.toml ]; then echo "[INFO] Poetry project detected" - pip install poetry tomli --root-user-action=ignore - - REPO_NAME=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["name"])') - REPO_URL=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["url"])') - - echo "[INFO] Configuring poetry source '$REPO_NAME' β†’ $REPO_URL" - poetry config virtualenvs.in-project true - poetry config repositories."$REPO_NAME" "$REPO_URL" - poetry config http-basic."$REPO_NAME" "$PYPI_USER" "$PYPI_PASS" - - poetry lock --no-cache --regenerate - poetry install - poetry add pylint --group dev + pip install poetry --root-user-action=ignore + poetry lock --no-update + poetry install --with dev elif [ -f requirements.txt ]; then echo "[INFO] Pip project detected" pip install -r requirements.txt --root-user-action=ignore - pip install pylint --root-user-action=ignore else - echo "[INFO] No dependency file found, installing pylint only" - pip install pylint --root-user-action=ignore + echo "[INFO] No dependency file found" fi - echo "πŸ§ͺ Running Pylint..." + echo "βœ… Installing pylint..." + pip install pylint --root-user-action=ignore || poetry add --dev pylint || echo "[WARN] Pylint μ„€μΉ˜ μ‹€νŒ¨" + + echo "πŸ§ͺ Running Pylint (JSON report)..." set +e + REPORT_FILE="/workspace/source/pylint-report.json" + if [ -f pyproject.toml ]; then - poetry run pylint $(params.pylint-args) . + poetry run pylint $(params.pylint-args) --output-format=json . > "$REPORT_FILE" else - pylint $(params.pylint-args) . + pylint $(params.pylint-args) --output-format=json . > "$REPORT_FILE" fi PYLINT_EXIT_CODE=$? set -e - echo "βœ… Pylint execution completed with exit code: $PYLINT_EXIT_CODE" - exit 0 # 항상 성곡 처리 (μ›λž˜ onError: continue 효과) + echo "$PYLINT_EXIT_CODE" > /tekton/results/pylint-exit-code + echo "πŸ“„ Pylint exit code: $PYLINT_EXIT_CODE" + + echo "πŸ“¦ Report saved to $REPORT_FILE" + head -n 10 "$REPORT_FILE" || echo "[WARN] Empty report" + + if [ "$(params.fail-on-lint)" = "true" ] && [ "$PYLINT_EXIT_CODE" -ne 0 ]; then + echo "❌ Pylint failed and fail-on-lint=true" + exit $PYLINT_EXIT_CODE + fi + + echo "βœ… Task succeeded regardless of lint result" + exit 0 diff --git a/tasks/pypi/task.yaml b/tasks/pypi/task.yaml index 477e768..02a802a 100644 --- a/tasks/pypi/task.yaml +++ b/tasks/pypi/task.yaml @@ -13,16 +13,6 @@ spec: description: Python version to use (e.g., 3.9, 3.11) default: "python:3.11-slim" - - name: pypi-username - type: string - description: PyPI username (fallback) - default: "" - - - name: pypi-password - type: string - description: PyPI password or token (fallback) - default: "" - - name: pypi-hosted-url type: string description: PyPI repository URL for upload @@ -31,54 +21,28 @@ spec: workspaces: - name: source description: Workspace containing the built artifacts - - name: pypi-auth - optional: true - description: | - A workspace containing: - - username - - password steps: - name: upload-to-pypi image: $(params.pythonImageName) workingDir: /workspace/source + env: + - name: HOME + value: /workspace/source/___HOME___ script: | #!/usr/bin/env bash set -e - TWINE_USERNAME="$(params.pypi-username)" - TWINE_PASSWORD="$(params.pypi-password)" HOSTED_URL="$(params.pypi-hosted-url)" - if [ -f /workspace/pypi-auth/username ]; then - TWINE_USERNAME=$(cat /workspace/pypi-auth/username) - fi - if [ -f /workspace/pypi-auth/password ]; then - TWINE_PASSWORD=$(cat /workspace/pypi-auth/password) - fi - + echo "πŸ“¦ Installing tools..." pip install --upgrade pip --root-user-action=ignore - pip install poetry twine --root-user-action=ignore - - # poetry 섀정이 ν•„μš”ν•œ 경우 pyproject.toml 뢄석 - if [ -f pyproject.toml ]; then - echo "[INFO] Using Poetry to install dependencies" - pip install poetry tomli --root-user-action=ignore - - REPO_NAME=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["name"])') - REPO_URL=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["url"])') - - echo "[INFO] Configuring poetry source '$REPO_NAME' β†’ $REPO_URL" - poetry config virtualenvs.in-project true - poetry config repositories."$REPO_NAME" "$REPO_URL" - poetry config http-basic."$REPO_NAME" "$TWINE_USERNAME" "$TWINE_PASSWORD" - fi + pip install poetry tomli twine --root-user-action=ignore echo "[INFO] Uploading artifacts to $HOSTED_URL" twine upload \ --repository-url "$HOSTED_URL" \ - --username "$TWINE_USERNAME" \ - --password "$TWINE_PASSWORD" \ "$(params.build-artifact-path)"/* echo "[INFO] βœ… Upload to PyPI complete" + diff --git a/tasks/pytest/task.yaml b/tasks/pytest/task.yaml index 17921e0..bbce771 100644 --- a/tasks/pytest/task.yaml +++ b/tasks/pytest/task.yaml @@ -14,93 +14,58 @@ spec: description: Python version to use (e.g., 3.9, 3.11) default: "python:3.11-slim" - - name: pypi-username - type: string - description: PyPI username (fallback) - default: "" - - - name: pypi-password - type: string - description: PyPI password or token (fallback) - default: "" - workspaces: - name: source description: Workspace containing the cloned Git repository from git-clone-checkout - - name: pypi-auth - optional: true - description: | - A workspace containing authentication credentials for a private PyPI repository. - Should include: - - username - - password - steps: - - name: install-dependencies - image: $(params.pythonImageName) - workingDir: /workspace/source - script: | - #!/usr/bin/env bash - set -e +- name: install-dependencies + image: $(params.pythonImageName) + workingDir: /workspace/source/$(params.subdirectory) + env: + - name: HOME + value: /workspace/shared/$(params.subdirectory)/___HOME___ + script: | + #!/usr/bin/env bash + set -e - if [ -n "$(params.subdirectory)" ]; then - cd "$(params.subdirectory)" - fi + echo "HOME=$HOME" + echo "πŸ”§ Installing dependencies..." - PYPI_USER="$(params.pypi-username)" - PYPI_PASS="$(params.pypi-password)" + pip install --upgrade pip --root-user-action=ignore + pip install pytest --root-user-action=ignore - if [ -f /workspace/pypi-auth/username ]; then - PYPI_USER=$(cat /workspace/pypi-auth/username) - fi - if [ -f /workspace/pypi-auth/password ]; then - PYPI_PASS=$(cat /workspace/pypi-auth/password) - fi + if [ -f pyproject.toml ]; then + echo "[INFO] Poetry project detected" + pip install poetry --root-user-action=ignore + echo "[INFO] Using pre-configured poetry settings from $HOME/.config/pypoetry/" + poetry lock --no-cache --no-update + poetry install + elif [ -f requirements.txt ]; then + echo "[INFO] Using pip to install dependencies" + pip install -r requirements.txt --root-user-action=ignore + else + echo "[WARN] No dependency file found" + fi - echo "πŸ”§ Installing dependencies..." - pip install --upgrade pip --root-user-action=ignore - pip install pytest --root-user-action=ignore + echo "πŸ§ͺ Running tests..." + set +e + if [ -f pyproject.toml ]; then + poetry run pytest --verbose --junitxml=/workspace/source/pytest-results.xml + else + pytest --verbose --junitxml=/workspace/source/pytest-results.xml + fi + TEST_EXIT_CODE=$? + set -e - if [ -f pyproject.toml ]; then - echo "[INFO] Poetry project detected" - pip install poetry tomli --root-user-action=ignore + echo "πŸ“„ Checking test results..." + if [ -f /workspace/source/pytest-results.xml ]; then + echo "Test results:" + cat /workspace/source/pytest-results.xml + else + echo "❌ No test results found" + exit 1 + fi - REPO_NAME=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["name"])') - REPO_URL=$(python3 -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["tool"]["poetry"]["source"][0]["url"])') - - echo "[INFO] Configuring poetry source '$REPO_NAME' β†’ $REPO_URL" - poetry config virtualenvs.in-project true - poetry config repositories."$REPO_NAME" "$REPO_URL" - poetry config http-basic."$REPO_NAME" "$PYPI_USER" "$PYPI_PASS" - - poetry lock --no-cache --regenerate - poetry install - elif [ -f requirements.txt ]; then - echo "[INFO] Using pip to install dependencies" - pip install -r requirements.txt --root-user-action=ignore - else - echo "[WARN] No dependency file found" - fi - - echo "πŸ§ͺ Running tests..." - set +e - if [ -f pyproject.toml ]; then - poetry run pytest --verbose --junitxml=/workspace/source/pytest-results.xml - else - pytest --verbose --junitxml=/workspace/source/pytest-results.xml - fi - TEST_EXIT_CODE=$? - set -e - - echo "πŸ“„ Checking test results..." - if [ -f /workspace/source/pytest-results.xml ]; then - echo "Test results:" - cat /workspace/source/pytest-results.xml - else - echo "❌ No test results found" - exit 1 - fi - - exit $TEST_EXIT_CODE \ No newline at end of file + exit $TEST_EXIT_CODE diff --git a/tasks/secret-home/task.yaml b/tasks/secret-home/task.yaml index 4b19c40..f714bae 100644 --- a/tasks/secret-home/task.yaml +++ b/tasks/secret-home/task.yaml @@ -14,29 +14,25 @@ spec: description: Name of the key(s) to extract from the secret workspaces: - - name: source + - name: shared description: Workspace containing the cloned Git repository + - name: secret + description: Secret data from workspace steps: - name: extract image: alpine:3.21.3 - workingDir: /workspace/source/$(params.subdirectory) + workingDir: /workspace/shared/$(params.subdirectory) script: | #!/bin/sh set -e - apk add --no-cache rsync + apk add --no-cache coreutils for key in $(params.keys); do - echo "Copying $key" - target="/workspace/source/$(params.subdirectory)/___HOME___/$key" + echo "encoding $key" + key_decoded=$(echo "$key" | sed 's/__/\//g') + echo "decoding $key_decoded" + target="/workspace/shared/$(params.subdirectory)/___HOME___/$key_decoded" mkdir -p "$(dirname "$target")" - rsync -R "/secrets/credentials/$key" "$(dirname "$target")" + cp "/secrets/credentials/$key" "$target" done - volumeMounts: - - name: credentials - mountPath: /secrets/credentials - - volumes: - - name: credentials - secret: - secretName: credentials