From 43505e0dfff66291700747b6482318e0b29a8f91 Mon Sep 17 00:00:00 2001 From: Pooria Shariatzadeh Date: Tue, 19 May 2026 21:51:05 +0330 Subject: [PATCH] add ci --- .dockerignore | 10 +++ .gitea/workflows/release-docker.yml | 46 ++++++++++++ .gitea/workflows/release-nuget.yml | 87 ++++++++++++++++++++++ CI_CHECKLIST.md | 20 +++++ DevOpsPackageTest/Class1.cs | 9 +++ DevOpsPackageTest/DevOpsPackageTest.csproj | 14 ++++ DevOpsTest.csproj | 2 +- DevOpsTest.sln | 8 +- Dockerfile | 25 +++++++ 9 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/release-docker.yml create mode 100644 .gitea/workflows/release-nuget.yml create mode 100644 CI_CHECKLIST.md create mode 100644 DevOpsPackageTest/Class1.cs create mode 100644 DevOpsPackageTest/DevOpsPackageTest.csproj create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..906956d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +**/.git +**/.gitea +**/.github +**/.vs +**/bin +**/obj +artifacts +Dockerfile* +*.user +*.suo diff --git a/.gitea/workflows/release-docker.yml b/.gitea/workflows/release-docker.yml new file mode 100644 index 0000000..fc6101d --- /dev/null +++ b/.gitea/workflows/release-docker.yml @@ -0,0 +1,46 @@ +name: Release Docker Image + +on: + release: + types: [published] + workflow_dispatch: + +env: + REGISTRY: reg.sabp.ir + IMAGE_NAME: sabp-apps/devops-test + RELEASE_TAG: ${{ gitea.event.release.tag_name }} + REF_NAME: ${{ gitea.ref_name }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Login to Harbor + shell: bash + env: + HARBOR_USERNAME: ${{ secrets.HARBOR_USERNAME }} + HARBOR_PASSWORD: ${{ secrets.HARBOR_PASSWORD }} + run: | + set -euo pipefail + if [ -z "${HARBOR_USERNAME:-}" ] || [ -z "${HARBOR_PASSWORD:-}" ]; then + echo "HARBOR_USERNAME and HARBOR_PASSWORD secrets are required." + exit 1 + fi + + echo "$HARBOR_PASSWORD" | docker login "$REGISTRY" --username "$HARBOR_USERNAME" --password-stdin + + - name: Build and push image + shell: bash + run: | + set -euo pipefail + tag="${RELEASE_TAG:-$REF_NAME}" + tag="${tag#v}" + image="$REGISTRY/$IMAGE_NAME" + + docker build --pull -t "$image:$tag" -t "$image:latest" . + docker push "$image:$tag" + docker push "$image:latest" diff --git a/.gitea/workflows/release-nuget.yml b/.gitea/workflows/release-nuget.yml new file mode 100644 index 0000000..f3c109d --- /dev/null +++ b/.gitea/workflows/release-nuget.yml @@ -0,0 +1,87 @@ +name: Release NuGet Packages + +on: + release: + types: [published] + workflow_dispatch: + +env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + NUGET_SOURCE_URL: https://nuget.sabp.ir/v3/index.json + PACKAGE_OUTPUT: ./artifacts/nuget + PACKAGE_PROJECTS: DevOpsPackageTest/DevOpsPackageTest.csproj + RELEASE_TAG: ${{ gitea.event.release.tag_name }} + REF_NAME: ${{ gitea.ref_name }} + +jobs: + pack-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x + + - name: Restore selected projects + shell: bash + run: | + set -euo pipefail + for project in $PACKAGE_PROJECTS; do + dotnet restore "$project" + done + + - name: Build selected projects + shell: bash + run: | + set -euo pipefail + for project in $PACKAGE_PROJECTS; do + dotnet build "$project" --configuration Release --no-restore + done + + - name: Pack selected projects + shell: bash + run: | + set -euo pipefail + mkdir -p "$PACKAGE_OUTPUT" + + version="${RELEASE_TAG:-$REF_NAME}" + version="${version#v}" + + for project in $PACKAGE_PROJECTS; do + dotnet pack "$project" \ + --configuration Release \ + --no-build \ + --output "$PACKAGE_OUTPUT" \ + -p:PackageVersion="$version" \ + -p:ContinuousIntegrationBuild=true + done + + - name: Push packages to BaGet + shell: bash + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: | + set -euo pipefail + if [ -z "${NUGET_API_KEY:-}" ]; then + echo "NUGET_API_KEY secret is required." + exit 1 + fi + + shopt -s nullglob + packages=("$PACKAGE_OUTPUT"/*.nupkg) + if [ ${#packages[@]} -eq 0 ]; then + echo "No NuGet packages were produced." + exit 1 + fi + + for package in "${packages[@]}"; do + dotnet nuget push "$package" \ + --source "$NUGET_SOURCE_URL" \ + --api-key "$NUGET_API_KEY" \ + --skip-duplicate + done diff --git a/CI_CHECKLIST.md b/CI_CHECKLIST.md new file mode 100644 index 0000000..43fb80c --- /dev/null +++ b/CI_CHECKLIST.md @@ -0,0 +1,20 @@ +# CI/CD Checklists + +## Can do in codebase + +- [x] Update Gitea release workflow to pack `DevOpsPackageTest/DevOpsPackageTest.csproj` +- [x] Update Gitea release workflow to restore/build/pack selected project paths only +- [x] Add Dockerfile for `DevOpsTest` +- [x] Add `.dockerignore` to keep build context clean +- [x] Add package metadata to `DevOpsPackageTest.csproj` + +## Cannot do from codebase alone + +- [ ] Create or verify Gitea repository secrets: `NUGET_API_KEY`, `HARBOR_USERNAME`, `HARBOR_PASSWORD` +- [ ] Create the actual Gitea release and confirm workflow triggers +- [ ] Confirm package upload success on `https://nuget.sabp.ir` +- [ ] Confirm Harbor project, credentials, and push permissions on `reg.sabp.ir` +- [ ] Confirm the published image is visible in Harbor and can be pulled by the production VM +- [ ] Run end-to-end smoke tests against the real registry and package server +- [ ] Validate the workflow against the real Gitea Actions runner environment + diff --git a/DevOpsPackageTest/Class1.cs b/DevOpsPackageTest/Class1.cs new file mode 100644 index 0000000..33c7b72 --- /dev/null +++ b/DevOpsPackageTest/Class1.cs @@ -0,0 +1,9 @@ +using System; + +namespace DevOpsPackageTest +{ + public class Class1 + { + + } +} diff --git a/DevOpsPackageTest/DevOpsPackageTest.csproj b/DevOpsPackageTest/DevOpsPackageTest.csproj new file mode 100644 index 0000000..ffc7b52 --- /dev/null +++ b/DevOpsPackageTest/DevOpsPackageTest.csproj @@ -0,0 +1,14 @@ + + + + netstandard2.1 + enable + true + false + DevOpsPackageTest + SABP + DevOps package test project for SABP CI/CD validation. + git + + + diff --git a/DevOpsTest.csproj b/DevOpsTest.csproj index 6568b3d..a3a34b6 100644 --- a/DevOpsTest.csproj +++ b/DevOpsTest.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable diff --git a/DevOpsTest.sln b/DevOpsTest.sln index 726161d..0a2b9b8 100644 --- a/DevOpsTest.sln +++ b/DevOpsTest.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.14.36616.10 d17.14 +VisualStudioVersion = 17.14.36616.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevOpsTest", "DevOpsTest.csproj", "{F5CD1119-847D-4C65-B472-C34A25F778CB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevOpsPackageTest", "DevOpsPackageTest\DevOpsPackageTest.csproj", "{BFABC423-0F62-D597-5CE8-75498604700E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {F5CD1119-847D-4C65-B472-C34A25F778CB}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5CD1119-847D-4C65-B472-C34A25F778CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {F5CD1119-847D-4C65-B472-C34A25F778CB}.Release|Any CPU.Build.0 = Release|Any CPU + {BFABC423-0F62-D597-5CE8-75498604700E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFABC423-0F62-D597-5CE8-75498604700E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFABC423-0F62-D597-5CE8-75498604700E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFABC423-0F62-D597-5CE8-75498604700E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cc3967d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# syntax=docker/dockerfile:1 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src + +COPY DevOpsTest.csproj ./ +RUN dotnet restore DevOpsTest.csproj + +COPY . ./ +RUN dotnet publish DevOpsTest.csproj \ + --configuration Release \ + --no-restore \ + --output /app/publish \ + /p:UseAppHost=false + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final +WORKDIR /app + +ENV ASPNETCORE_URLS=http://+:8080 \ + ASPNETCORE_ENVIRONMENT=Production + +EXPOSE 8080 + +COPY --from=build /app/publish ./ +ENTRYPOINT ["dotnet", "DevOpsTest.dll"]