Building an Automated Deployment Workflow in a Traditional IT Environment
Introduction
The company is in a traditional industry and operates across several factories. Many information systems are managed independently, with different people and responsibilities for servers, deployment environments, and development environments. Because of this, even when better tools or processes are available, we cannot simply decide to introduce them. That creates quite a few environmental limitations.
The goal of this workflow is not to build the newest or most complete automated deployment platform. It is to work within the current limitations and:
- Reduce repetitive manual work.
- Standardize the deployment sequence so it can be handed over to someone else later.
- Check the Build and required settings before deployment to avoid deploying a broken version.
- Keep historical artifacts that can be restored manually.
Current Workflow Summary
The deployment process starts when I manually run a PowerShell program, so it is not completely automated. After starting the deployment program, the workflow is:
- Run
git pullfor the version to be deployed. - Choose whether the target is the test or production environment.
- Build the C# backend project and Vue frontend project.
- Stop if the Build throws an error, then inspect the error manually and notify the relevant developer.
- Check the required settings after a successful Build.
- Package the backend and frontend separately after the settings pass validation.
- Create an SSH connection based on the selected environment, then upload both archives to the corresponding server through SFTP.
- Run commands through SSH to extract the archives on the remote server, then execute its deployment program.
- The remote deployment program is provided by that server's administrator, so the remaining process is outside the scope of this article.
Technologies Used
| Purpose | Technology | Current responsibility |
|---|---|---|
| Source control | Git | Manages the C# backend and Vue frontend source code |
| Workflow control | PowerShell | Connects validation, Build, packaging, uploads, and remote commands |
| Backend build | .NET CLI | Uses dotnet publish to generate backend deployment files |
| Frontend build | pnpm | Runs the frontend Build Script defined in package.json |
| Packaging | 7-Zip | Compresses the backend and frontend artifacts into separate ZIP files |
| Remote transfer | Posh-SSH/SFTP | Uploads ZIP artifacts to the remote server |
| Remote operations | Posh-SSH/SSH | Extracts archives and runs the remote deployment program |
| Historical artifacts | Date-based folders | Stores artifacts under yyyyMMdd for tracing and manual restoration. Deployments are infrequent, so one version per day is currently enough. |
Detailed Architecture
Manually get the latest code: git pull
│
▼
Run the deployment program and select the environment (test/production)
│
▼
Build backend: dotnet publish
│ └─ Failure → Stop
▼
Pre-deployment validation: verify configuration format and required values
│ └─ Missing value or invalid format → Stop
▼
Build frontend: pnpm run build
│ └─ Failure → Stop
▼
Package: compress backend and frontend artifacts separately with 7-Zip
│ └─ Failure → Stop
▼
Upload: transfer ZIP files through SFTP
│ └─ Failure → Stop
▼
Remote extraction: run unzip through SSH
│ └─ Exit Status is not 0 → Stop
▼
Remote deployment: run the remote deployment program through SSH
│ └─ Exit Status is not 0 → Stop
▼
CompleteSelecting the Deployment Environment
- Select the target environment when starting the deployment program:
- Test.
- Production.
- Load different settings for the selected environment:
- Remote server.
- SFTP/SSH connection information.
- Local project and output paths.
- Remote upload and deployment paths.
- Backend and frontend environment settings.
- Use parameters to switch environments within the same deployment program instead of maintaining separate copies of the workflow.
Deployment Settings
- Keep server, path, account, and other environment settings separate from the PowerShell workflow logic.
- Passwords are not written directly into the deployment program. They are read from a separate encrypted password file or entered manually when the program runs.
- For convenience, paths, IP addresses, and other non-password settings are currently written directly in the program.
Problems the Current Workflow Has Solved
- Combines separate Build, compression, upload, and remote operations behind a single entry point.
- Standardizes the workflow for test and production environments.
- Stops deployment after a Build failure.
- Checks configuration file formatting and required fields before uploading.
- Captures the Exit Status and error messages when remote commands fail.
- Keeps historical ZIP artifacts so an older version remains available for manual restoration.
Future Improvements
Linking Deployment Actions to Git Commits
- Run a program on the production and test servers to monitor Git, or check it on a schedule. If the deployment branch has a new version, pull and deploy it automatically, so developers only need to Push.
- Alternatively, create a dedicated deployment server that monitors or periodically checks Git, retrieves new versions, runs compilation checks, and deploys them to the corresponding servers.
- The required security checks and controls still need to be implemented.
- A separate process for restoring older versions is also required.
Adding Post-deployment Health Checks
- Create a validation process after the remote update:
- Check whether the backend API responds successfully.
- Check whether the frontend home page is accessible.
- Check whether the service process is running normally.
- A successful file upload or completed remote deployment program should not be enough to declare the whole deployment successful.
Adding Logs and Audit Information
- Store information such as the deployment time, Git version, and result for future reference.
- This could be stored in a
.logfile or a database.
- This could be stored in a
Docker Deployment
- If Docker can eventually be installed on the deployment server, the whole project could be moved into Docker.
Building a Complete CI/CD Workflow
If I have the chance to learn a complete CI/CD workflow in the future, I will review this deployment process again and build a more reliable solution.
Conclusion
This workflow is not the best possible solution, but I am keeping a record in case it helps someone working under similar constraints.
English translation provided by Codex.