Hello, my name is Cem Levent Avcı. I am a senior Computer Engineering student at Eskişehir Osmangazi University. At the same time, I work on both my personal portfolio projects and freelance projects I take on. I develop applications in both frontend and backend, mainly using technologies such as Laravel, Next.js, and C#. I also strive to automate my projects with CI/CD pipelines. In this article, I will walk you step by step through the process of automatically building a C# backend project using GitHub Actions and deploying it via FTP.

What is GitHub Actions and What Does It Do?

GitHub Actions is a CI/CD (Continuous Integration / Continuous Deployment) tool that runs directly on GitHub. In other words, with this tool, we can automatically test, build, and deploy every change made in our project.

What is CI/CD?

  • Continuous Integration is the process where code changes are continuously integrated into the main project. Each change goes through automated tests, and errors are detected at an early stage. This helps teams maintain high code quality and minimize conflicts.

  • Continuous Deployment / Delivery is the process of automatically deploying code that has passed the tests to the production or staging environment. While Continuous Delivery requires manual approval for deployment, Continuous Deployment happens fully automatically. This way, new features or fixes can quickly reach the users.

What Does GitHub Actions Provide Us?

GitHub Actions is a tool that increases automation, reduces errors, and simplifies workflow management in modern software development processes. Here are its main advantages:

  1. Automated Build and Test: Every change made in the Git repository is automatically tested and built thanks to GitHub Actions. This ensures that errors are detected before the project progresses and prevents faulty code from being pushed to production. Automated testing and build processes improve project quality while also saving developers time.

  2. Continuous Integration and Deployment: The CI/CD mechanism enables code to be continuously integrated and deployed without manual intervention. Developers can define separate jobs for environments like development, staging, and production. This way, new features or fixes can be delivered to users quickly and securely.

  3. Workflow Management with Version Control: All workflow steps are stored inside the repository as .yml files and kept under version control. This allows workflow changes to be tracked just like code changes and collaboratively improved by team members. Workflow management enhances team coordination and standardizes processes.

  4. Flexibility and Integration: GitHub Actions works seamlessly with different languages and platforms such as Node.js, C#, Python, and Java. It can also integrate with popular deployment and service tools like Docker, Kubernetes, FTP, AWS, and Azure. Workflows can be further customized with conditions, parallel jobs, and caching mechanisms, making processes more flexible and optimized.

  5. Speed and Efficiency: Since repetitive tasks are automated, developers can use their time more efficiently. Testing, building, and deployment processes become standardized; human errors are minimized, and projects can be delivered to production faster.

Creating a Sample C# Backend Deployment Workflow with GitHub Actions

1. Git Repository File Structure

my-repo/
├─ .github/
│  └─ workflows/
│     └─ deploy.yml      # Github Actions workflow file
├─ backend_api/
│  ├─ backend_api.sln            # Solution file
│  ├─ backend_api.csproj         # Project file
│  ├─ Program.cs                 
│  ├─ ...
└─ README.md

2.deploy.yml file

name: Backend Deploy via FTP  # @1

on: # @2
  push:
    branches:
      - main

jobs: # @3
  backend-deploy:
    runs-on: ubuntu-latest
    steps:  # @4
      - name: Checkout code #  @5
        uses: actions/checkout@v4

      - name: Setup .NET 9
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: "9.0.x"

      - name: Restore dependencies
        run: dotnet restore ./backend_api/backend_api.sln

      - name: Publish backend
        run: dotnet publish ./backend_api/backend_api.csproj -c Release -o ./backend/publish

      - name: Verify templates are included  # optional
        run: |
          echo "Checking if templates are included in publish output..."
          ls -la ./backend/publish/templates/
          echo "Template files found:"
          find ./backend/publish/templates/ -name "*.html" -type f

      - name: Deploy backend via FTP
        uses: SamKirkland/FTP-Deploy-Action@v4.3.5
        with:
          protocol: ftp
          port: 21
          timeout: 190000
          log-level: verbose
          server: ${{ secrets.FTP_SERVER }}
          username: ${{ secrets.FTP_USERNAME }}
          password: ${{ secrets.FTP_PASSWORD }}
          local-dir: ./backend/publish/
          server-dir: /api.yourdomain.com/

  1. The name: parameter is the name that will appear in the GitHub Actions workflow panel. You can name it however you want it to be displayed there.

  2. The on: parameter defines under which conditions the workflow will run. In the current deploy.yml file, the workflow will be triggered on every push to the main branch of our repository, and the deployment process will begin.

  3. The jobs: parameter defines the jobs within the workflow. In our current workflow, only one job named backend-deploy is defined. The runs-on: parameter specifies the operating system on which this job will run.

  4. The steps: parameter defines the sequential steps that will be executed inside a job. From this point onward, the actions to be performed are listed step by step with different names.

    • In the name: Checkout code step, the code from our repository is pulled into the workflow environment.

    • In the name: Setup .NET 9 step, the .NET SDK 9 is installed in the workflow environment. This allows the C# backend project to be built and published using this version.

    • In the name: Restore dependencies step, all NuGet packages in the project are downloaded. The required dependencies are thus prepared for the build and publish processes.

    • In the name: Publish backend step, the project is compiled in Release mode, and the files to be published are output into the ./backend/publish folder. This folder will then be sent to the server via FTP.

    • The name: Verify templates are included step is optional. You may not need to include this step in your own workflow. In my case, since my project required HTML templates, I added this verification to ensure they were included before deploying to the server. In short, this step checks whether the relevant files exist in the workflow.

    • In the name: Deploy backend via FTP step, the files we just published are uploaded to the server via FTP using SamKirkland/FTP-Deploy-Action@v4.3.5. For this step to work, you must add FTP credentials as repository secrets under “Secrets and Variables” → “Actions secrets” in your repository settings. These secrets should include:

      • FTP_SERVER (the IP address or domain of the FTP server)

      • FTP_USERNAME

      • FTP_PASSWORD

    • By setting log-level: verbose, you can view the FTP upload process and any errors in detail. The local-dir parameter specifies the path of the files we previously published, indicating where to take the files from. The server-dir parameter specifies where the files will be uploaded on the server. For example, you can create a subdomain in the Plesk panel and deploy under it (which is what I did). If you want to deploy directly to the main domain, you can change it to /httpdocs/ in Plesk, depending on your needs.

Thank you for reading! I hope the information I shared about automating the deployment process of C# backend projects with GitHub Actions has been helpful to you.

Please feel free to reach out to me for any questions, feedback, or project collaborations. Exchanging ideas on technology, software, and automation, as well as discussing new projects, is always very valuable to me.

You can contact me through the following channels:

  • Email: cemlevent54@gmail.com

  • LinkedIn: linkedin.com/in/leventavci54

  • GitHub: github.com/cemlevent54

  • Personal Website: https://cemleventavci.com.tr – You can visit to see my portfolio and the projects I’ve worked on.

Author

Cem Levent

Cem Levent

I write about software development, technology and personal experiences.