diff --git a/.gitea/workflows/container.yml b/.gitea/workflows/container.yml deleted file mode 100644 index 0b7d42a..0000000 --- a/.gitea/workflows/container.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Build and Push Docker Image - -on: - push: - branches: [ main, dev ] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - env: - GIT_SSL_NO_VERIFY: true - - - name: Login to Registry - uses: docker/login-action@v2 - with: - registry: ${{ vars.REGISTRY_HOST }} - username: ${{ secrets.REGISTRY_USER }} - password: ${{ secrets.REGISTRY_PASSWORD }} - - - name: Build Docker Image - env: - BRANCH_NAME: ${{ github.ref_name }} - SHORT_HASH: ${{ github.sha }} - run: | - # Build the image with the commit hash tag - docker build --build-arg BUILD_IDENTIFIER=${SHORT_HASH:0:5} -t ${{ vars.REGISTRY_HOST }}/${GITHUB_REPOSITORY}:${BRANCH_NAME}-${SHORT_HASH:0:5} . - - # Tag the same image as "latest" - docker tag ${{ vars.REGISTRY_HOST }}/${GITHUB_REPOSITORY}:${BRANCH_NAME}-${SHORT_HASH:0:5} ${{ vars.REGISTRY_HOST }}/${GITHUB_REPOSITORY}:${BRANCH_NAME}-latest - - - name: Push Docker Images - env: - BRANCH_NAME: ${{ github.ref_name }} - SHORT_HASH: ${{ github.sha }} - run: | - docker push ${{ vars.REGISTRY_HOST }}/${GITHUB_REPOSITORY}:${BRANCH_NAME}-${SHORT_HASH:0:5} - docker push ${{ vars.REGISTRY_HOST }}/${GITHUB_REPOSITORY}:${BRANCH_NAME}-latest - - - name: Log out from registry - if: always() - run: docker logout ${{ vars.REGISTRY_HOST }} - diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d3b6f8b..a5f09de 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,8 +27,6 @@ test: stage: test image: "$CI_REGISTRY_IMAGE:job-$CI_PIPELINE_ID" script: - - node --version - - npm --version - python --version - nikola --version - pip --version @@ -39,9 +37,8 @@ deploy: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker pull $CI_REGISTRY_IMAGE:job-$CI_PIPELINE_ID - - docker tag $CI_REGISTRY_IMAGE:job-$CI_PIPELINE_ID $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_SLUG:-latest} - - echo "deploying $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_SLUG:-latest}" - - docker push $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_SLUG:-latest} + - docker tag $CI_REGISTRY_IMAGE:job-$CI_PIPELINE_ID $CI_REGISTRY_IMAGE:latest + - docker push $CI_REGISTRY_IMAGE:latest include: - template: Security/SAST.gitlab-ci.yml - template: Security/Container-Scanning.gitlab-ci.yml diff --git a/Dockerfile b/Dockerfile index 4e0e9d0..74bd758 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,13 @@ -FROM docker.io/library/alpine:3.23 AS cabuilder -RUN apk add --no-cache ca-certificates python3 py3-requests -ADD bin/fetch_letsencrypt_ca_certs.py /usr/local/bin/fetch_letsencrypt_ca_certs.py -RUN /usr/local/bin/fetch_letsencrypt_ca_certs.py /usr/local/share/ca-certificates/ -RUN update-ca-certificates - FROM docker.io/library/python:3.11-alpine -RUN apk --no-cache add sshpass openssh-client lftp nodejs npm; mkdir -p /opt/app +RUN apk --no-cache add sshpass openssh-client lftp; mkdir -p /opt/app WORKDIR /opt/app ADD requirements.txt /root/ ADD Dockerfile /root/ ADD bin/*.sh /usr/local/bin/ -COPY --from=cabuilder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt # ignore "Running pip as root" warning ENV PIP_ROOT_USER_ACTION=ignore -ENV REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt RUN chmod 755 /usr/local/bin/*.sh && pip install -r /root/requirements.txt && pip freeze && rm -Rf "$(pip cache dir)" diff --git a/README.md b/README.md index 2c7e363..966be18 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # deployment-helper für Nikola based Websites -## ENV-Variables +# ENV-Variables * LFTP_PASSWORD (Deployment-Passwort for sftp-Upload) * SSH_HOST (Deployment-Host for sftp-Upload) @@ -11,27 +11,6 @@ This image is based on the python:3.11-alpine image and includes additional Python-packages for building nikola-sites. -## Configure your project - -| Variable | Default | Description | -| --------------------------- | --------------- | ---------------------------------------- | -| DEPLOY_HELPER_ENABLE_NIKOLA | true | Build Nikola-Website in `website/` | -| DEPLOY_HELPER_ENABLE_NODE | false | Enable nodejs Build in `node/` | -| DEPLOY_HELPER_CONTENT_DIR | website/output/ | Default Content-Directory for publishing | - - -Create a configuration file in your git-repo: `.deployment-helper`: - -``` -DEPLOY_HELPER_ENABLE_NIKOLA=false -DEPLOY_HELPER_ENABLE_NODE=true -DEPLOY_HELPER_CONTENT_DIR="node/.output/public/" -``` - -This example disables the niko build and enables node. The finished -website is copied from the `node/.output/public/` directory to the -target server. - ## lftp for sftp-Uploads This image includes `lftp` to upload files to a sftp-server and use diff --git a/bin/build.sh b/bin/build.sh index 9311cd3..727aa8f 100644 --- a/bin/build.sh +++ b/bin/build.sh @@ -1,76 +1,18 @@ #!/bin/sh -# Default configurations: -DEPLOY_HELPER_ENABLE_NIKOLA=true -DEPLOY_HELPER_ENABLE_NODE=false - -if test -f .deployment-helper +if ! test -d website then - # shellcheck source=/dev/null - . .deployment-helper + echo "Website directory not found" + exit 1 fi - - -if $DEPLOY_HELPER_ENABLE_NODE +if ! command -v nikola >/dev/null 2>&1 then - if ! command -v node >/dev/null 2>&1 - then - echo "node not found" 1>&2 - exit 1 - fi - if ! command -v npm >/dev/null 2>&1 - then - echo "npm not found" 1>&2 - exit 1 - fi - if ! test -d node - then - echo "Node directory not found" 1>&2 - exit 1 - fi - - cd node || { echo 'Directory "node" not found'; exit 1;} - if ! npm install - then - echo "Error installing node-dependencies" 1>&2 - exit 1 - fi - if test -f nuxt.config.ts - then - # Build for nuxi based Sites - if ! npx nuxi build - then - echo "Error nuxi build" 1>&2 - exit 1 - fi - if ! npx nuxi generate - then - echo "Error nuxi generate" 1>&2 - exit 1 - fi - else - echo "No supportet node website type found" 1>&2 - exit 1 - fi - cd .. + echo "nikola command not found" + exit 1 fi -if $DEPLOY_HELPER_ENABLE_NIKOLA -then - if ! test -d website - then - echo "Website directory not found" 1>&2 - exit 1 - fi +cd website - if ! command -v nikola >/dev/null 2>&1 - then - echo "nikola command not found" 1>&2 - exit 1 - fi - cd website || { echo 'Directory "website" not found'; exit 1;} - nikola build - cd .. -fi +nikola build exit "$?" diff --git a/bin/deploy.sh b/bin/deploy.sh index 154fa0f..bdf78f1 100755 --- a/bin/deploy.sh +++ b/bin/deploy.sh @@ -1,16 +1,7 @@ #!/bin/sh -# Default configurations: -DEPLOY_HELPER_CONTENT_DIR="website/output" -if test -f .deployment-helper -then - # shellcheck source=/dev/null - . .deployment-helper -fi - - -if ! test -d "${DEPLOY_HELPER_CONTENT_DIR}" +if ! test -d website/output then echo "Website-Build not found" exit 1 @@ -25,9 +16,6 @@ then fi -lftp -e "set sftp:auto-confirm yes; mirror -R ${DEPLOY_HELPER_CONTENT_DIR} ./web/; bye" \ - --env-password \ - -u ${SSH_USER} \ - sftp://${SSH_HOST} +lftp -e 'set sftp:auto-confirm yes; mirror -R ./website/output/ ./web/; bye' --env-password -u ${SSH_USER} sftp://${SSH_HOST} diff --git a/bin/fetch_letsencrypt_ca_certs.py b/bin/fetch_letsencrypt_ca_certs.py deleted file mode 100755 index 85eb8f3..0000000 --- a/bin/fetch_letsencrypt_ca_certs.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import requests -from html.parser import HTMLParser -from urllib.parse import urljoin - -LETSENCRYPT_CERT_PAGE = "https://letsencrypt.org/certificates/" -DEFAULT_TARGET_DIR = "./letsencrypt-ca" - - -class PemLinkParser(HTMLParser): - def __init__(self): - super().__init__() - self.pem_links = set() - - def handle_starttag(self, tag, attrs): - if tag.lower() != "a": - return - for attr, value in attrs: - if attr == "href" and value.lower().endswith(".pem"): - self.pem_links.add(value) - - -def fetch_certificate_page(): - resp = requests.get(LETSENCRYPT_CERT_PAGE, timeout=15) - resp.raise_for_status() - return resp.text - - -def extract_pem_links(html): - parser = PemLinkParser() - parser.feed(html) - return sorted( - urljoin(LETSENCRYPT_CERT_PAGE, link) - for link in parser.pem_links - ) - - -def download_and_store(url, target_dir): - base_name = os.path.basename(url) - # Zielname = .crt statt .pem - target_name = os.path.splitext(base_name)[0] + ".crt" - target_path = os.path.join(target_dir, target_name) - - if os.path.exists(target_path): - print(f"[=] Bereits vorhanden: {target_name}") - return target_name - - print(f"[+] Lade herunter: {base_name}") - resp = requests.get(url, timeout=15) - resp.raise_for_status() - - if b"BEGIN CERTIFICATE" not in resp.content: - print(f"[!] Ungültiges Zertifikat: {base_name}") - return None - - # Direkt als .crt speichern (PEM-Inhalt) - with open(target_path, "wb") as f: - f.write(resp.content) - - return target_name - - -def list_local_crt_files(target_dir): - return { - f for f in os.listdir(target_dir) - if f.lower().endswith(".crt") - } - - -def main(): - target_dir = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_TARGET_DIR - os.makedirs(target_dir, exist_ok=True) - - print(f"[*] Zielverzeichnis: {os.path.abspath(target_dir)}") - print("[*] Format: PEM-Inhalt mit .crt-Endung") - - html = fetch_certificate_page() - pem_urls = extract_pem_links(html) - - # Remote-Dateinamen im .crt-Format - remote_files = { - os.path.splitext(os.path.basename(url))[0] + ".crt" - for url in pem_urls - } - - for url in pem_urls: - download_and_store(url, target_dir) - - local_files = list_local_crt_files(target_dir) - orphaned = sorted(local_files - remote_files) - - print("\n" + "=" * 60) - if orphaned: - print("[!] Lokal vorhanden, aber nicht mehr gelistet:") - for f in orphaned: - print(f" - {f}") - else: - print("[✓] Keine veralteten Dateien gefunden") - print("=" * 60) - print("[✓] Fertig.") - - -if __name__ == "__main__": - main() - -