diff --git a/.github/workflows/push.functions.yml b/.github/workflows/push.functions.yml deleted file mode 100644 index 2527e1d8..00000000 --- a/.github/workflows/push.functions.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: Push Events (Functions) - -on: - push: - branches: - - main - - dev - paths: - - "src/functions/**" - - ".github/workflows/push.functions.yml" - -concurrency: - group: "${{ github.workflow }}-${{ github.ref }}-functions" - cancel-in-progress: true - -jobs: - test-unit: - name: Unit test - runs-on: ubuntu-latest - - steps: - - name: โฌ‡๏ธ Set up code - uses: actions/checkout@v4 - with: - show-progress: false - - - name: โŽ” Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: lts/* - cache: npm - cache-dependency-path: src/functions/package-lock.json - - - name: ๐Ÿ“ฅ Download dependencies - run: npm ci - working-directory: src/functions - - - name: ๐Ÿงช Run tests - run: npm test - working-directory: src/functions - - deploy-dev: - name: Deploy to dev - runs-on: ubuntu-latest - needs: [test-unit] - permissions: - id-token: write - contents: read - environment: - name: dev - if: github.ref_name == 'dev' - - steps: - - name: โฌ‡๏ธ Set up code - uses: actions/checkout@v4 - with: - show-progress: false - - - id: auth - name: ๐Ÿ—๏ธ Authenticate to Google Cloud - uses: google-github-actions/auth@v2 - with: - create_credentials_file: true - token_format: access_token - workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} - service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} - - - name: ๐Ÿš€ Deploy Cloud Function - id: deploy - uses: google-github-actions/deploy-cloud-functions@v3 - timeout-minutes: 10 - with: - name: pdf - runtime: nodejs20 - source_dir: src/functions - memory: 512M - entry_point: generate - service_account: cloud-function-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com - service_timeout: "2m" - environment_variables: |- - BUCKET=${{ vars.BUCKET }} - WATERMARK=true - - deploy-prod: - name: Deploy to prod - runs-on: ubuntu-latest - needs: [test-unit] - permissions: - id-token: write - contents: read - environment: - name: prod - if: github.ref_name == 'main' - - steps: - - name: โฌ‡๏ธ Set up code - uses: actions/checkout@v4 - with: - show-progress: false - - - id: auth - name: ๐Ÿ—๏ธ Authenticate to Google Cloud - uses: google-github-actions/auth@v2 - with: - create_credentials_file: true - token_format: access_token - workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} - service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} - - - name: ๐Ÿš€ Deploy Cloud Function - id: deploy - uses: google-github-actions/deploy-cloud-functions@v3 - with: - name: pdf - runtime: nodejs20 - source_dir: src/functions - memory: 512M - entry_point: generate - service_account: cloud-function-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com - service_timeout: "2m" - environment_variables: |- - BUCKET=${{ vars.BUCKET }} - WATERMARK=false diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 5f884f8d..44fc270d 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -3,20 +3,35 @@ name: Push Events on: push: branches: - - main - dev - paths: - - "src/**" - - "!src/functions/**" - - ".github/workflows/push.yml" + - main concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: - test-unit: - name: Unit test + release-please: + name: Create release + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: ๐Ÿš€ Create Release + id: release-please + uses: agrc/release-composite-action@v1 + with: + prerelease: ${{ github.ref_name == 'dev' }} + repo-token: ${{ secrets.GITHUB_TOKEN }} + github-app-id: ${{ secrets.UGRC_RELEASE_BOT_APP_ID }} + github-app-key: ${{ secrets.UGRC_RELEASE_BOT_APP_KEY }} + github-app-name: ${{ secrets.UGRC_RELEASE_BOT_NAME }} + github-app-email: ${{ secrets.UGRC_RELEASE_BOT_EMAIL }} + + test-unit-app: + name: Unit test app runs-on: ubuntu-latest steps: @@ -40,16 +55,9 @@ jobs: run: npm test working-directory: src/api/uic-inventory/ - deploy-dev: - name: Deploy to dev + test-unit-functions: + name: Unit test functions runs-on: ubuntu-latest - needs: [test-unit] - permissions: - id-token: write - contents: read - environment: - name: dev - if: github.ref_name == 'dev' steps: - name: โฌ‡๏ธ Set up code @@ -57,167 +65,17 @@ jobs: with: show-progress: false - - id: auth - name: ๐Ÿ—๏ธ Authenticate to Google Cloud - uses: google-github-actions/auth@v2 - with: - create_credentials_file: true - token_format: access_token - workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} - service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} - - - name: ๐Ÿณ Set up Docker Buildx - id: builder - uses: docker/setup-buildx-action@v3 - - - name: ๐Ÿท๏ธ Extract tags from GitHub - id: meta - uses: docker/metadata-action@v5 - with: - images: us-central1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/images/api - tags: | - type=ref,suffix=-{{sha}},event=branch - type=ref,prefix=pr-,suffix=-{{sha}},event=pr - type=semver,pattern={{version}} - type=raw,value=latest - - - name: ๐Ÿ—๏ธ Authenticate Docker to Google CLoud - uses: docker/login-action@v3 - with: - registry: us-central1-docker.pkg.dev - username: oauth2accesstoken - password: ${{ steps.auth.outputs.access_token }} - - - name: ๐Ÿ“ฆ Build and push image - uses: docker/build-push-action@v6 - with: - file: ./src/api/Api.Dockerfile - provenance: false - builder: ${{ steps.builder.outputs.name }} - build-args: VITE_API_KEY=${{ secrets.AGRC_API_KEY }} - tags: ${{ steps.meta.outputs.tags }} - context: . - push: true - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: ๐Ÿ”๏ธ Set image name - run: | - IMAGE_ID=$(echo $DOCKER_METADATA_OUTPUT_TAGS | cut -d ' ' -f 1) - echo "IMAGE_ID=$IMAGE_ID" >> $GITHUB_ENV - - - name: ๐Ÿš€ Deploy to Cloud Run - id: deploy - uses: google-github-actions/deploy-cloudrun@v2 - with: - service: uic-inventory-api - image: ${{ env.IMAGE_ID }} - region: us-central1 - flags: | - --service-account=cloud-run-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com - --set-cloudsql-instances=${{ secrets.CLOUD_SQL }} - --vpc-connector=${{ secrets.VPC }} - --vpc-egress=private-ranges-only - --max-instances=5 - --concurrency=250 - --cpu=1 - --memory=512Mi - --timeout=5m - env_vars: > - ASPNETCORE_URLS=http://+:8080, - ASPNETCORE_ENVIRONMENT=Production, - UPLOAD_BUCKET=${{ secrets.PROJECT_ID }}-unscanned, - STORAGE_BUCKET=${{ secrets.PROJECT_ID }}-documents - secrets: | - /secrets/dotnet/appsettings.Production.json=dotnet-appsettings:latest - - deploy-prod: - name: Deploy to prod - runs-on: ubuntu-latest - needs: [test-unit] - permissions: - id-token: write - contents: read - environment: - name: prod - if: github.ref_name == 'main' - - steps: - - name: โฌ‡๏ธ Set up code - uses: actions/checkout@v4 - with: - show-progress: false - - - id: auth - name: ๐Ÿ—๏ธ Authenticate to Google Cloud - uses: google-github-actions/auth@v2 - with: - create_credentials_file: true - token_format: access_token - workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} - service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} - - - name: ๐Ÿณ Set up Docker Buildx - id: builder - uses: docker/setup-buildx-action@v3 - - - name: ๐Ÿท๏ธ Extract tags from GitHub - id: meta - uses: docker/metadata-action@v5 - with: - images: us-central1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/images/api - tags: | - type=ref,suffix=-{{sha}},event=branch - type=ref,prefix=pr-,suffix=-{{sha}},event=pr - type=semver,pattern={{version}} - type=raw,value=latest - - - name: ๐Ÿ—๏ธ Authenticate Docker to Google CLoud - uses: docker/login-action@v3 - with: - registry: us-central1-docker.pkg.dev - username: oauth2accesstoken - password: ${{ steps.auth.outputs.access_token }} - - - name: ๐Ÿ“ฆ Build and push image - uses: docker/build-push-action@v6 + - name: โŽ” Setup Node.js + uses: actions/setup-node@v4 with: - file: ./src/api/Api.Dockerfile - provenance: false - builder: ${{ steps.builder.outputs.name }} - build-args: VITE_API_KEY=${{ secrets.AGRC_API_KEY }} - tags: ${{ steps.meta.outputs.tags }} - context: . - push: true - cache-from: type=gha - cache-to: type=gha,mode=max + node-version: lts/* + cache: npm + cache-dependency-path: src/functions/package-lock.json - - name: ๐Ÿ”๏ธ Set image name - run: | - IMAGE_ID=$(echo $DOCKER_METADATA_OUTPUT_TAGS | cut -d ' ' -f 1) - echo "IMAGE_ID=$IMAGE_ID" >> $GITHUB_ENV + - name: ๐Ÿ“ฅ Download dependencies + run: npm ci + working-directory: src/functions - - name: ๐Ÿš€ Deploy to Cloud Run - id: deploy - uses: google-github-actions/deploy-cloudrun@v2 - with: - service: uic-inventory-api - image: ${{ env.IMAGE_ID }} - region: us-central1 - flags: | - --service-account=cloud-run-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com - --set-cloudsql-instances=${{ secrets.CLOUD_SQL }} - --vpc-connector=${{ secrets.VPC }} - --vpc-egress=private-ranges-only - --max-instances=5 - --concurrency=250 - --cpu=1 - --memory=512Mi - --timeout=5m - env_vars: > - ASPNETCORE_URLS=http://+:8080, - ASPNETCORE_ENVIRONMENT=Production, - UPLOAD_BUCKET=${{ secrets.PROJECT_ID }}-unscanned, - STORAGE_BUCKET=${{ secrets.PROJECT_ID }}-documents - secrets: | - /secrets/dotnet/appsettings.Production.json=dotnet-appsettings:latest + - name: ๐Ÿงช Run tests + run: npm test + working-directory: src/functions diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..5f8f1173 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,283 @@ +name: Release Events + +on: + release: + types: [published] + workflow_dispatch: + inputs: + environment: + description: 'Environment to run tests against' + type: environment + required: true + +permissions: + id-token: write + deployments: write + contents: read + +jobs: + deploy-dev-app: + name: Deploy app to staging + runs-on: ubuntu-latest + environment: + name: dev + url: https://uic-inventory.dev.utah.gov/ + if: github.event.release.prerelease == true || inputs.environment == 'dev' + + steps: + - name: โฌ‡๏ธ Set up code + uses: actions/checkout@v4 + with: + show-progress: false + + - id: auth + name: ๐Ÿ—๏ธ Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + create_credentials_file: true + token_format: access_token + workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} + service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} + + - name: ๐Ÿณ Set up Docker Buildx + id: builder + uses: docker/setup-buildx-action@v3 + + - name: ๐Ÿท๏ธ Extract tags from GitHub + id: meta + uses: docker/metadata-action@v5 + with: + images: us-central1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/images/api + tags: | + type=ref,suffix=-{{sha}},event=branch + type=ref,prefix=pr-,suffix=-{{sha}},event=pr + type=semver,pattern={{version}} + type=raw,value=latest + + - name: ๐Ÿ—๏ธ Authenticate Docker to Google CLoud + uses: docker/login-action@v3 + with: + registry: us-central1-docker.pkg.dev + username: oauth2accesstoken + password: ${{ steps.auth.outputs.access_token }} + + - name: ๐Ÿ“ฆ Build and push image + uses: docker/build-push-action@v6 + with: + file: ./src/api/Api.Dockerfile + provenance: false + builder: ${{ steps.builder.outputs.name }} + build-args: VITE_API_KEY=${{ secrets.AGRC_API_KEY }} + tags: ${{ steps.meta.outputs.tags }} + context: . + push: true + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: ๐Ÿ”๏ธ Set image name + run: | + IMAGE_ID=$(echo $DOCKER_METADATA_OUTPUT_TAGS | cut -d ' ' -f 1) + echo "IMAGE_ID=$IMAGE_ID" >> $GITHUB_ENV + + - name: ๐Ÿš€ Deploy to Cloud Run + id: deploy + uses: google-github-actions/deploy-cloudrun@v2 + with: + service: uic-inventory-api + image: ${{ env.IMAGE_ID }} + region: us-central1 + flags: | + --service-account=cloud-run-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com + --set-cloudsql-instances=${{ secrets.CLOUD_SQL }} + --vpc-connector=${{ secrets.VPC }} + --vpc-egress=private-ranges-only + --max-instances=5 + --concurrency=250 + --cpu=1 + --memory=512Mi + --timeout=5m + env_vars: > + ASPNETCORE_URLS=http://+:8080, + ASPNETCORE_ENVIRONMENT=Production, + UPLOAD_BUCKET=${{ secrets.PROJECT_ID }}-unscanned, + STORAGE_BUCKET=${{ secrets.PROJECT_ID }}-documents + secrets: | + /secrets/dotnet/appsettings.Production.json=dotnet-appsettings:latesty + + deploy-prod-app: + name: Deploy app to production + runs-on: ubuntu-latest + environment: + name: prod + url: https://uic-inventory.deq.utah.gov/ + if: github.event.release.prerelease == false || inputs.environment == 'prod' + + steps: + - name: โฌ‡๏ธ Set up code + uses: actions/checkout@v4 + with: + show-progress: false + + - id: auth + name: ๐Ÿ—๏ธ Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + create_credentials_file: true + token_format: access_token + workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} + service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} + + - name: ๐Ÿณ Set up Docker Buildx + id: builder + uses: docker/setup-buildx-action@v3 + + - name: ๐Ÿท๏ธ Extract tags from GitHub + id: meta + uses: docker/metadata-action@v5 + with: + images: us-central1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/images/api + tags: | + type=ref,suffix=-{{sha}},event=branch + type=ref,prefix=pr-,suffix=-{{sha}},event=pr + type=semver,pattern={{version}} + type=raw,value=latest + + - name: ๐Ÿ—๏ธ Authenticate Docker to Google CLoud + uses: docker/login-action@v3 + with: + registry: us-central1-docker.pkg.dev + username: oauth2accesstoken + password: ${{ steps.auth.outputs.access_token }} + + - name: ๐Ÿ“ฆ Build and push image + uses: docker/build-push-action@v6 + with: + file: ./src/api/Api.Dockerfile + provenance: false + builder: ${{ steps.builder.outputs.name }} + build-args: VITE_API_KEY=${{ secrets.AGRC_API_KEY }} + tags: ${{ steps.meta.outputs.tags }} + context: . + push: true + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: ๐Ÿ”๏ธ Set image name + run: | + IMAGE_ID=$(echo $DOCKER_METADATA_OUTPUT_TAGS | cut -d ' ' -f 1) + echo "IMAGE_ID=$IMAGE_ID" >> $GITHUB_ENV + + - name: ๐Ÿš€ Deploy to Cloud Run + id: deploy + uses: google-github-actions/deploy-cloudrun@v2 + with: + service: uic-inventory-api + image: ${{ env.IMAGE_ID }} + region: us-central1 + flags: | + --service-account=cloud-run-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com + --set-cloudsql-instances=${{ secrets.CLOUD_SQL }} + --vpc-connector=${{ secrets.VPC }} + --vpc-egress=private-ranges-only + --max-instances=5 + --concurrency=250 + --cpu=1 + --memory=512Mi + --timeout=5m + env_vars: > + ASPNETCORE_URLS=http://+:8080, + ASPNETCORE_ENVIRONMENT=Production, + UPLOAD_BUCKET=${{ secrets.PROJECT_ID }}-unscanned, + STORAGE_BUCKET=${{ secrets.PROJECT_ID }}-documents + secrets: | + /secrets/dotnet/appsettings.Production.json=dotnet-appsettings:latest + + deploy-dev-functions: + name: Deploy functions to staging + runs-on: ubuntu-latest + environment: + name: dev + if: github.event.release.prerelease == true || inputs.environment == 'dev' + + steps: + - name: โฌ‡๏ธ Set up code + uses: actions/checkout@v4 + with: + show-progress: false + + - id: auth + name: ๐Ÿ—๏ธ Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + create_credentials_file: true + token_format: access_token + workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} + service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} + + - name: ๐Ÿš€ Deploy Cloud Function + id: deploy + uses: google-github-actions/deploy-cloud-functions@v3 + timeout-minutes: 10 + with: + name: pdf + runtime: nodejs20 + source_dir: src/functions + memory: 512M + entry_point: generate + service_account: cloud-function-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com + service_timeout: "2m" + environment_variables: |- + BUCKET=${{ vars.BUCKET }} + WATERMARK=true + + deploy-prod-functions: + name: Deploy functions to production + runs-on: ubuntu-latest + environment: + name: prod + if: github.event.release.prerelease == false || inputs.environment == 'prod' + + steps: + - name: โฌ‡๏ธ Set up code + uses: actions/checkout@v4 + with: + show-progress: false + + - id: auth + name: ๐Ÿ—๏ธ Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + create_credentials_file: true + token_format: access_token + workload_identity_provider: ${{ secrets.IDENTITY_PROVIDER }} + service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }} + + - name: ๐Ÿš€ Deploy Cloud Function + id: deploy + uses: google-github-actions/deploy-cloud-functions@v3 + with: + name: pdf + runtime: nodejs20 + source_dir: src/functions + memory: 512M + entry_point: generate + service_account: cloud-function-sa@${{ secrets.PROJECT_ID }}.iam.gserviceaccount.com + service_timeout: "2m" + environment_variables: |- + BUCKET=${{ vars.BUCKET }} + WATERMARK=false + + notify: + name: Notifications + runs-on: ubuntu-latest + needs: deploy-prod + permissions: + contents: read + pull-requests: write + issues: write + + steps: + - name: Release Notifier + uses: agrc/release-issue-notifications-action@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }}