├── Views ├── _ViewStart.cshtml ├── _ViewImports.cshtml ├── Home │ ├── Privacy.cshtml │ └── Index.cshtml └── Shared │ ├── _ValidationScriptsPartial.cshtml │ ├── Error.cshtml │ ├── _Layout.cshtml.css │ └── _Layout.cshtml ├── wwwroot ├── favicon.ico ├── js │ └── site.js └── css │ └── site.css ├── Models └── ErrorViewModel.cs ├── LevelUpDevOps.slnx ├── appsettings.Development.json ├── appsettings.json ├── .gitignore ├── LevelUpDevOps.csproj ├── .dockerignore ├── .github └── workflows │ ├── docker-pr.yaml │ └── docker-kubernetes.yaml ├── README.md ├── Dockerfile ├── Properties └── launchSettings.json ├── Program.cs ├── Controllers └── HomeController.cs └── k8s.yaml /Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robrich/levelup-devops-github-actions-kubernetes/HEAD/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using LevelUpDevOps 2 | @using LevelUpDevOps.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Views/Home/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Privacy Policy"; 3 | } 4 |
Use this page to detail your site's privacy policy.
7 | -------------------------------------------------------------------------------- /Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace LevelUpDevOps.Models; 2 | 3 | public class ErrorViewModel 4 | { 5 | public string? RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | -------------------------------------------------------------------------------- /LevelUpDevOps.slnx: -------------------------------------------------------------------------------- 1 |Learn about building Web apps with ASP.NET Core.
8 |
12 | Request ID: @Model.RequestId
13 |
18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |
20 |21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |
26 | -------------------------------------------------------------------------------- /Views/Shared/_Layout.cshtml.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | a { 11 | color: #0077cc; 12 | } 13 | 14 | .btn-primary { 15 | color: #fff; 16 | background-color: #1b6ec2; 17 | border-color: #1861ac; 18 | } 19 | 20 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link { 21 | color: #fff; 22 | background-color: #1b6ec2; 23 | border-color: #1861ac; 24 | } 25 | 26 | .border-top { 27 | border-top: 1px solid #e5e5e5; 28 | } 29 | .border-bottom { 30 | border-bottom: 1px solid #e5e5e5; 31 | } 32 | 33 | .box-shadow { 34 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 35 | } 36 | 37 | button.accept-policy { 38 | font-size: 1rem; 39 | line-height: inherit; 40 | } 41 | 42 | .footer { 43 | position: absolute; 44 | bottom: 0; 45 | width: 100%; 46 | white-space: nowrap; 47 | line-height: 60px; 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/docker-kubernetes.yaml: -------------------------------------------------------------------------------- 1 | name: Docker build, Kubernetes Run 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | 15 | - uses: actions/checkout@v4 16 | 17 | - name: Docker Login 18 | uses: docker/login-action@v3.5.0 19 | with: 20 | registry: ${{ secrets.ACR_URL }} 21 | username: ${{ secrets.ACR_USERNAME }} 22 | password: ${{ secrets.ACR_PASSWORD }} 23 | logout: true 24 | 25 | - name: Kubernetes Set Context 26 | uses: Azure/k8s-set-context@v3.0 27 | with: 28 | method: kubeconfig 29 | kubeconfig: ${{ secrets.KUBE_CONFIG }} 30 | 31 | - name: docker build & push, kubectl apply 32 | run: | 33 | docker build -t ${{ secrets.ACR_URL }}/levelupdevops:${{ github.sha }} . 34 | docker push ${{ secrets.ACR_URL }}/levelupdevops:${{ github.sha }} 35 | sed -i'' -e 's/ACR_URL/${{ secrets.ACR_URL }}/g' -e 's/AKS_URL/${{ secrets.AKS_URL }}/g' -e 's/IMAGE_LABEL/${{ github.sha }}/g' k8s.yaml 36 | kubectl apply -f k8s.yaml 37 | -------------------------------------------------------------------------------- /k8s.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: levelupdevops 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: levelupdevops 10 | template: 11 | metadata: 12 | labels: 13 | app: levelupdevops 14 | version: IMAGE_LABEL 15 | spec: 16 | containers: 17 | - name: levelupdevops 18 | image: ACR_URL/levelupdevops:IMAGE_LABEL 19 | resources: 20 | limits: 21 | memory: "128Mi" 22 | cpu: "500m" 23 | requests: 24 | memory: "64Mi" 25 | cpu: "250m" 26 | ports: 27 | - containerPort: 8080 28 | env: 29 | - name: ASPNETCORE_ENVIRONMENT 30 | value: "Production" 31 | - name: ASPNETCORE_URLS 32 | value: "http://+:8080" 33 | - name: ConnectionStrings__MyDB 34 | value: "Server=tcp:SQL_SERVER,1433;Initial Catalog=MyDB;Persist Security Info=False;User ID=SQL_USER;Password=SQL_PASSWORD;..." 35 | --- 36 | apiVersion: v1 37 | kind: Service 38 | metadata: 39 | name: levelupdevops 40 | spec: 41 | selector: 42 | app: levelupdevops 43 | ports: 44 | - port: 8080 45 | targetPort: 8080 46 | --- 47 | apiVersion: networking.k8s.io/v1 48 | kind: Ingress 49 | metadata: 50 | name: levelupdevops 51 | annotations: 52 | cert-manager.io/cluster-issuer: letsencrypt 53 | acme.cert-manager.io/http01-edit-in-place: "true" 54 | spec: 55 | ingressClassName: nginx 56 | tls: 57 | - hosts: 58 | - levelupdevops.AKS_URL 59 | secretName: tls-secret 60 | rules: 61 | - host: levelupdevops.AKS_URL 62 | http: 63 | paths: 64 | - pathType: Prefix 65 | path: "/" 66 | backend: 67 | service: 68 | name: levelupdevops 69 | port: 70 | number: 8080 71 | -------------------------------------------------------------------------------- /Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |