ARTICLE AD BOX
I am trying to run a simple GitLab CI pipeline, but it fails with a syntax error.
Error:
jobs config should contain at least one visible job
Here is my .gitlab-ci.yml file:
What I’m trying to do
I want to create a basic CI pipeline that runs a simple build job and prints a message to confirm the pipeline is working correctly.
⚙️ What I expected
I expected the pipeline to run successfully and execute the build_job, printing the message in the job logs.
❌ What actually happens
The pipeline fails before execution with the error:
jobs config should contain at least one visible job🔍 Additional details
I am using a shared GitLab Runner
The repository is hosted on GitLab
The .gitlab-ci.yml file is located in the root directory
💡 Possible causes (you can also check before posting)
This error usually happens if:
The job is missing required keywords like script
The job is filtered out using rules, only, or except
YAML formatting/indentation is incorrect
The job is considered hidden (e.g., starts with a dot like .build_job)
# SPYK3-PHISH GitLab CI/CD Pipeline - Alpine Optimized # Simplified and error-free version image: alpine:latest stages: - test - build - scan - release - deploy variables: DOCKER_IMAGE: $CI_REGISTRY_IMAGE DOCKER_TAG: $CI_COMMIT_SHORT_SHA PYTHON_VERSION: "3.11" # Cache for pip packages cache: paths: - .cache/pip - .venv/ # Test stage - Alpine optimized test: stage: test image: python:3.11-alpine before_script: - apk add --no-cache git gcc musl-dev python3-dev - python -m venv .venv - source .venv/bin/activate - pip install --cache-dir .cache/pip --upgrade pip - pip install --cache-dir .cache/pip flake8 pytest pytest-cov script: - source .venv/bin/activate - python -m py_compile spyk3_phish.py - flake8 spyk3_phish.py --max-line-length=120 || true - python -c "import ast; ast.parse(open('spyk3_phish.py').read()); print('✅ Syntax OK')" artifacts: paths: - .venv/ expire_in: 1 hour only: - main - develop - merge_requests # Security scan with Bandit security-scan: stage: scan image: python:3.11-alpine before_script: - apk add --no-cache git - python -m venv .venv - source .venv/bin/activate - pip install --cache-dir .cache/pip bandit safety script: - source .venv/bin/activate - bandit -r . -f json -o bandit-report.json || true - safety check --json > safety-report.json || true artifacts: paths: - bandit-report.json - safety-report.json expire_in: 7 days only: - main - develop # Build Alpine Docker image build: stage: build image: docker:latest services: - docker:dind variables: DOCKER_TLS_CERTDIR: "/certs" before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker build --pull -t $DOCKER_IMAGE:$DOCKER_TAG -f Dockerfile.alpine . - docker tag $DOCKER_IMAGE:$DOCKER_TAG $DOCKER_IMAGE:alpine-latest - docker push $DOCKER_IMAGE:$DOCKER_TAG - docker push $DOCKER_IMAGE:alpine-latest only: - main - develop tags: - docker # Container security scan with Trivy container-scan: stage: scan image: docker:latest services: - docker:dind variables: TRIVY_VERSION: "0.45.0" before_script: - apk add --no-cache curl - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v${TRIVY_VERSION} script: - trivy image --severity HIGH,CRITICAL --no-progress --exit-code 0 --format json --output trivy-report.json $DOCKER_IMAGE:$DOCKER_TAG artifacts: paths: - trivy-report.json expire_in: 7 days only: - main allow_failure: true # Secret detection secret-scan: stage: scan image: python:3.11-alpine before_script: - apk add --no-cache git - pip install detect-secrets script: - detect-secrets scan --all-files > secrets-report.json || true artifacts: paths: - secrets-report.json expire_in: 7 days only: - main - develop allow_failure: true # Release stable version release: stage: release image: docker:latest services: - docker:dind before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker pull $DOCKER_IMAGE:$DOCKER_TAG - docker tag $DOCKER_IMAGE:$DOCKER_TAG $DOCKER_IMAGE:stable - docker tag $DOCKER_IMAGE:$DOCKER_TAG $DOCKER_IMAGE:latest - docker push $DOCKER_IMAGE:stable - docker push $DOCKER_IMAGE:latest only: - main when: manual # Deploy to test environment deploy-test: stage: deploy image: alpine:latest before_script: - apk add --no-cache openssh-client - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - - mkdir -p ~/.ssh - chmod 700 ~/.ssh - ssh-keyscan $TEST_SERVER_IP >> ~/.ssh/known_hosts script: - | ssh $TEST_SERVER_USER@$TEST_SERVER_IP " docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA docker stop spyk3-phish 2>/dev/null || true docker rm spyk3-phish 2>/dev/null || true docker run -d \ --name spyk3-phish \ --restart unless-stopped \ -p 8080:8080 \ -v spyk3_data:/app/.spyk3_phish \ -e SPYK3_MODE=production \ $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA " environment: name: test url: http://$TEST_SERVER_IP:8080 only: - develop when: manual # Documentation pages pages: stage: deploy image: alpine:latest script: - mkdir -p public - | cat > public/index.html << 'EOF' <!DOCTYPE html> <html> <head> <title>SPYK3-PHISH v11.0.0</title> <style> body { font-family: Arial, sans-serif; margin: 40px; } h1 { color: #2c3e50; } ul { line-height: 1.8; } .badge { display: inline-block; padding: 5px 10px; background: #3498db; color: white; border-radius: 3px; } </style> </head> <body> <h1>🔒 SPYK3-PHISH v11.0.0</h1> <p><span class="badge">Cybersecurity Command Center</span></p> <h2>Features</h2> <ul> <li>5000+ Security Commands</li> <li>Multi-Platform Bot Integration</li> <li>Advanced Phishing Suite</li> <li>SSH Remote Access</li> <li>Traffic Generation</li> </ul> <h2>Docker Images</h2> <ul> <li>Alpine Linux (Lightweight)</li> <li>Ubuntu Linux (Full-featured)</li> </ul> <p><strong>Repository:</strong> $CI_REGISTRY_IMAGE</p> </body> </html> EOF artifacts: paths: - public only: - mainenter image description here