diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bd4d6332..53f28b3e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,101 +1,90 @@ stages: - - test - - scan + - deploy -cache: - paths: - - .sonar/cache - - .cache - -# ====================================================== -# ๐Ÿงช Step 1: Unit Test + Coverage -# ====================================================== -unit_test: - stage: test - image: golang:1.23 - services: - - name: redis:7-alpine - alias: redis +deploy-dev: + stage: deploy + image: alpine:3.20 variables: - REDIS_HOST: redis - REDIS_PORT: 6379 - script: - - echo "๐Ÿงช Menjalankan unit test..." - - go mod tidy - - go test ./... -coverprofile=coverage.out || true - - go tool cover -func=coverage.out | tail -n 1 - artifacts: - when: always - paths: - - coverage.out - expire_in: 1 week - only: - - devops-ec2 + DEPLOY_APP: "LTI-MBUGROUP" + # Opsional: kalau pakai submodule, ini bikin clone submodule pakai SSH juga + GIT_SUBMODULE_STRATEGY: recursive + GIT_DEPTH: "1" -# ====================================================== -# ๐Ÿ”’ Step 2: Security Scan (Gosec) -# ====================================================== -gosec_scan: - stage: scan - image: golang:1.24 - script: - - apt-get update && apt-get install -y jq - - go install github.com/securego/gosec/v2/cmd/gosec@latest - - echo "๐Ÿ” Menjalankan scan keamanan dengan gosec..." - - gosec -fmt=json -out=gosec-report.json ./... || true - - echo "๐Ÿ“„ Jumlah issue ditemukan:" && cat gosec-report.json | jq '.Issues | length' - # Konversi hasil gosec ke format SonarQube - - | - jq -r '.Issues[] | { - engineId: "gosec", - ruleId: .rule_id, - primaryLocation: { - message: .details, - filePath: .file, - textRange: {startLine: .line} - }, - type: "VULNERABILITY", - severity: (if .severity == "HIGH" then "CRITICAL" elif .severity == "MEDIUM" then "MAJOR" else "MINOR" end) - }' gosec-report.json | jq -s '{issues: .}' > gosec-generic-report.json - artifacts: - when: always - paths: - - gosec-report.json - - gosec-generic-report.json - expire_in: 1 week - allow_failure: false - only: - - devops-ec2 + before_script: + - echo "๐Ÿงฐ Installing dependencies..." + - apk update && apk add --no-cache openssh git curl bash + + # Setup SSH di runner + - mkdir -p ~/.ssh + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa + - chmod 600 ~/.ssh/id_rsa + - eval "$(ssh-agent -s)" + - ssh-add ~/.ssh/id_rsa + + # Trust host keys (server + gitlab) biar SSH gak nanya interaktif + - ssh-keyscan -H "$SERVER_IP" >> ~/.ssh/known_hosts + - ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts -# ====================================================== -# ๐Ÿ“Š Step 3: SonarQube Analysis -# ====================================================== -sonarqube_analysis: - stage: scan - image: sonarsource/sonar-scanner-cli:latest script: - - apk add --no-cache jq - - echo "๐Ÿš€ Mengirim analisis ke SonarQube..." - - | - sonar-scanner \ - -Dsonar.projectKey=mbu-lti-backend \ - -Dsonar.projectName="MBU LTI Backend" \ - -Dsonar.sources=. \ - -Dsonar.host.url=https://status.mbugroup.id/sonar \ - -Dsonar.login=sqp_57fbffb8337608c331091dd1544569df613a2d3f \ - -Dsonar.go.coverage.reportPaths=coverage.out \ - -Dsonar.externalIssuesReportPaths=gosec-generic-report.json \ - -Dsonar.sourceEncoding=UTF-8 \ - -Dsonar.verbose=true - dependencies: - - unit_test - - gosec_scan - artifacts: - when: always - paths: - - .scannerwork - - coverage.out - - gosec-generic-report.json - expire_in: 1 week + - echo "๐Ÿš€ Deploying latest code to $SERVER_USER@$SERVER_IP" + + - > + if ssh -o StrictHostKeyChecking=no "$SERVER_USER@$SERVER_IP" " + set -e + + cd /home/devops/docker/deployment/development/lti-api + + # Pastikan remote origin SSH (antisipasi kalau pernah ke-set HTTPS) + git remote set-url origin git@gitlab.com:mbugroup/lti-api.git + + # Pastikan server percaya gitlab.com juga (untuk git fetch via SSH) + mkdir -p ~/.ssh + ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts + + # Fetch/reset pakai SSH + GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=no' git fetch origin development + git reset --hard origin/development + + docker compose restart dev-api-lti || docker compose up -d dev-api-lti + "; then + STATUS='success'; + else + STATUS='failed'; + fi; + + RUN_URL="${CI_PROJECT_URL}/-/pipelines/${CI_PIPELINE_ID}"; + + if [ "$STATUS" = "success" ]; then + COLOR=3066993; + TITLE="โœ… Deployment API Succeeded"; + DESC="Deployment job on branch \`${CI_COMMIT_REF_NAME}\` completed successfully."; + else + COLOR=15158332; + TITLE="โŒ Deployment API Failed Gaes"; + DESC="Deployment job on branch \`${CI_COMMIT_REF_NAME}\` failed."; + fi; + + echo "{ + \"username\": \"CI Bot\", + \"embeds\": [{ + \"title\": \"$TITLE\", + \"description\": \"$DESC\", + \"color\": $COLOR, + \"fields\": [ + {\"name\": \"Repository\", \"value\": \"${CI_PROJECT_PATH}\", \"inline\": true}, + {\"name\": \"Actor\", \"value\": \"${GITLAB_USER_LOGIN}\", \"inline\": true}, + {\"name\": \"Commit\", \"value\": \"${CI_COMMIT_SHA}\", \"inline\": false}, + {\"name\": \"Pipeline\", \"value\": \"[Open run](${RUN_URL})\", \"inline\": false} + ] + }] + }" > payload.json; + + echo "๐Ÿ“ก Sending notification to Discord..."; + curl -sS -H "Content-Type: application/json" \ + -d @payload.json "$DISCORD_WEBHOOK_URL"; + only: - - devops-ec2 \ No newline at end of file + - development + + environment: + name: development \ No newline at end of file