// Engineering Log
Secure Development: Part 1 — CI/CD: From Manual Deployments to Automated Deployments
Published on 2026-09-22
// Fast route
This article belongs to the topic Deploy and reliability.
CI/CD is the practice where every code change is automatically built, tested and delivered to the server. Instead of the manual sequence “copy files, restart the service and check that nothing broke”, this work is performed by a program according to a description stored in the repository alongside the code.
This part starts the series on secure development. All the following checks — secret scanning, static code analysis, dependency and container image checks — are integrated into the pipeline, so you have to start with it.
CI, CD and CD again
- Continuous Integration (Continuous Integration). After each
git pushthe code is built and tests are run. A bug is discovered minutes after the commit, not on release day. - Continuous Delivery (Continuous Delivery). Each successful build is ready for deployment, but a person gives the command to deploy.
- Continuous Deployment (Continuous Deployment). A successful build is deployed to the server automatically, without human intervention.
Small teams usually prefer the second model: everything is checked automatically, and deployment is triggered with a single button.
What a pipeline consists of
- A description file in the repository:
.gitlab-ci.yml,.github/workflows/*.yml,.gitea/workflows/*.yamlorJenkinsfile. - Stages and jobs. Stages are executed in order; jobs within a stage run in parallel if there are enough runners.
- Runner — a program that executes jobs. GitLab.com and GitHub.com provide cloud runners; on a self-hosted GitLab or Gitea server you need to install and register a runner yourself.
- Variables and secrets are set in the project settings, not in the pipeline file.
Tools
GitLab CI is built into GitLab — both cloud GitLab.com and the self-hosted edition. The pipeline is described in .gitlab-ci.yml at the repository root. On your own GitLab server jobs will run only after installing and registering GitLab Runner.
GitHub Actions is built into GitHub. Pipeline files live in .github/workflows, and there is a large marketplace of ready-made actions for common steps.
Gitea Actions appeared in Gitea 1.19, and have been enabled by default since version 1.21. The syntax is mostly compatible with GitHub Actions; files are placed in .gitea/workflows/, and jobs are executed by the separate Gitea Runner program. This is a lightweight option for a company that needs its own Git server with built-in automation.
Jenkins is a separate automation server: pipelines are described in a Jenkinsfile, and functionality is extended with plugins. It is very flexible, but you are responsible for installation, updates and plugin compatibility. It is usually chosen where it is already in long-term use.
Minimal working pipeline
Example for GitLab CI: tests on every change and deployment only from the main branch.
stages:
- test
- deploy
test:
stage: test
image: python:3.13-slim
script:
- pip install -r requirements.txt
- pytest
deploy:
stage: deploy
script:
- ./deploy.sh
environment: production
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manualThe deploy job appears only on the main branch and waits for manual start — that’s Continuous Delivery. If you remove when: manual, you get Continuous Deployment.
Same for GitHub Actions — file .github/workflows/ci.yml:
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
container: python:3.13-slim
steps:
- uses: actions/checkout@v6
- run: pip install -r requirements.txt
- run: pytestAlmost the same file works for Gitea Actions, only placed in .gitea/workflows/.
Where in the pipeline security checks occur
| Where | What is checked | Part of the cycle |
|---|---|---|
| On the developer before commit and the first pipeline job | Passwords and keys in code | Part 2 — Secrets |
| With tests | Vulnerable patterns in your own code | Part 3 — SAST |
| With tests | Known vulnerabilities and licenses of dependencies | Part 4 — SCA |
| Image build | Reproducibility, cache, secrets during build | Part 5 — Dockerfile |
| After build and at runtime | Image vulnerabilities, container privileges | Part 6 — Containers |
A check is useful only if it can stop the pipeline: warnings that don’t affect anything quickly stop being read. A reasonable approach is to enable the check in report mode, review the findings, and then make it mandatory.
Pipeline secrets and access
- Passwords and keys are stored in protected project variables (in GitLab — masked and protected, in GitHub — secrets), not in the YAML file.
- Create a separate user and key for deployment with minimal permissions — only what’s necessary for the deployment.
- Deployment is allowed only from the main branch.
- A runner on a private server should not run jobs of other projects: Gitea documentation explicitly warns not to use untrusted runners or to provide your runners to untrusted instances.
GitOps
For Kubernetes, the GitOps approach is widespread: the desired state of the cluster is described in Git, and a special agent in the cluster (Argo CD or Flux) brings the cluster to that description. In this case the pipeline does not deploy the application directly, but only updates the manifests in the repository. For one or two servers without Kubernetes this is unnecessary complexity — a normal deployment step is enough.
What to consider in Russia
- It’s not possible to pay for foreign GitHub and GitLab.com plans with a card from a Russian bank: Visa and Mastercard have not worked outside Russia since March 2022.
- Independence from external services is provided by a self-hosted Git server — GitLab on your own server or Gitea with Gitea Actions — and runners on your own machines. This option requires administration, but code, builds and secrets remain under your control.
Common mistakes
- Passwords in the pipeline file. They end up in Git history and are visible to everyone who has access to the repository.
- Checks that do not stop the build. Their results are not reviewed.
- Long pipeline. If a build takes half an hour, developers stop waiting for results. Caching dependencies and parallel jobs help.
- Deploying from any branch. Experimental code reaches the production server.
- One runner with production access for all projects. A bug or compromise in one project opens access to the others.
Pipeline setup for a specific project — from initial tests to deployment to your own servers — is included in the CI/CD setup service.
// Similar task
If you are dealing with something similar
This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.
Article topic
Deploy and reliability
Docker, CI/CD, releases, monitoring, observability, and incident handling.
Typical tasks behind this topic
- Set up deployment without manual chaos
- Add monitoring, alerts, and baseline observability
- Investigate incidents and stabilize production
// Next step
If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.
Open services// Reviews
Related reviews
I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler, more affordable solution. In the end I saved time and money. Mikhail — a true expert who works for the client's result, not for the fee. I recommend him!
I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler and more cost-effective solution. In the end I saved budget and time. Mikhail — a true expert who …
VPS setup, server setup
2026-05-12 · ★ 5/5
Excellent work! Set up the server very quickly, installed the control panel, and configured the IP. Definitely recommend!
Excellent work! Very quickly set up the server, installed the panel, configured the IP I can definitely recommend it!
Everything was excellent; helped promptly and professionally. Thank you — I recommend them to the community.
Everything's great, helped promptly and professionally, thank you, I recommend it to the community
VPS setup, server setup
2026-04-16 · ★ 5/5
There were several issues concerning both the technical side and overall understanding. Mikhail responded quickly, resolved the technical problems, and helped me understand them — many thanks. I'm satisfied with the result.
There were several issues concerning both the technical side and overall understanding. Mikhail responded quickly to the request, helped sort things out and resolved the technical problems and helped clarify …
VPS setup, server setup
2026-02-18 · ★ 5/5
Everything was done quickly and efficiently. I recommend.
Everything was done quickly and efficiently. I recommend.
VPS setup, server setup
2026-01-17 · ★ 5/5
Everything went well; the contractor responded quickly to questions and helped resolve the issue. Thanks!
Everything went well, the contractor responded quickly to questions and helped resolve the issue. Thank you!
VPS setup, server setup
2025-12-16 · ★ 5/5
// Contact
Need help?
Get in touch with me and I'll help solve the problem
I reply within one business day (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related