diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..8a6369b --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,82 @@ +name: BuildEngine v2 Deploy to AWS + +on: + workflow_call: + inputs: + BUILD_NUMBER: + type: 'string' + required: true + ECS_CLUSTER: + type: 'string' + required: true + DOCKER_TAG: + type: 'string' + required: true + BUILD_ENGINE_BUILD_TAG: + type: 'string' + required: true + OTEL_BUILD_TAG: + type: 'string' + required: true + secrets: + AWS_ACCESS_KEY_ID: + required: true + AWS_SECRET_ACCESS_KEY: + required: true + AWS_DEFAULT_REGION: + required: true + AWS_ECR_ACCOUNT: + required: true + +jobs: + deploy-to-ecr: + runs-on: ubuntu-latest + steps: + - name: Pull from GHCR + run: | + docker pull ghcr.io/sillsdev/appbuilder-buildengine-api:${{ inputs.DOCKER_TAG }} + docker pull ghcr.io/sillsdev/appbuilder-buildengine-otel:${{ inputs.DOCKER_TAG }} + + - name: Configure AWS credentials + id: aws + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_DEFAULT_REGION }} + + - name: Login to AWS ECR + id: ecr + uses: aws-actions/amazon-ecr-login@v2 + with: + registries: ${{ secrets.AWS_ECR_ACCOUNT }} + + - name: Build deployment target variables + id: vars + run: | + echo "Setting up deployment variables..." + echo "IMAGE_URL=${{ steps.ecr.outputs.registry }}/appbuilder-buildengine-api-origin" >> $GITHUB_OUTPUT + echo "OTEL_URL=${{ steps.ecr.outputs.registry }}/appbuilder-buildengine-api-otel-collector" >> $GITHUB_OUTPUT + + - name: Push to AWS ECR + run: | + docker tag ${{ inputs.BUILD_ENGINE_BUILD_TAG}} "${{ steps.vars.outputs.IMAGE_URL }}:${{ inputs.DOCKER_TAG }}" + docker tag ${{ inputs.BUILD_ENGINE_BUILD_TAG}} "${{ steps.vars.outputs.IMAGE_URL }}:${{ inputs.BUILD_NUMBER }}" + docker tag ${{ inputs.OTEL_BUILD_TAG}} "${{ steps.vars.outputs.OTEL_URL }}:${{ inputs.DOCKER_TAG }}" + docker tag ${{ inputs.OTEL_BUILD_TAG}} "${{ steps.vars.outputs.OTEL_URL }}:${{ inputs.BUILD_NUMBER }}" + echo "Docker images tagged as ${{ inputs.DOCKER_TAG }} and ${{ inputs.BUILD_NUMBER }}" + + docker push "${{ steps.vars.outputs.IMAGE_URL }}:${{ inputs.DOCKER_TAG }}" + docker push "${{ steps.vars.outputs.IMAGE_URL }}:${{ inputs.BUILD_NUMBER }}" + echo "Docker images pushed successfully to ${{ steps.vars.outputs.IMAGE_URL }}" + + docker push "${{ steps.vars.outputs.OTEL_URL }}:${{ inputs.DOCKER_TAG }}" + docker push "${{ steps.vars.outputs.OTEL_URL }}:${{ inputs.BUILD_NUMBER }}" + echo "Docker images pushed successfully to ${{ steps.vars.outputs.OTEL_URL }}" + + - name: Deploy to ECS + if: ${{ inputs.ECS_CLUSTER != 'none' }} + run: | + echo "Deploying ${{ inputs.BUILD_NUMBER }} to ${{ inputs.ECS_CLUSTER }}" + # Deploy to ECS cluster with service name 'build-engine', setting all images to the latest tag + ecs-deploy -c ${{ inputs.ECS_CLUSTER }} -n buildengine -i ignore -to ${{ inputs.BUILD_NUMBER }} --max-definitions 20 --timeout 600 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e715feb..8436919 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,61 +1,38 @@ -name: BuildEngine CI +name: BuildEngine v2 Test and Deploy on: push: - branches: [master, develop, github-builds] - pull_request: workflow_dispatch: inputs: - logLevel: - description: "Log Level" - required: true - default: "warning" tags: description: "Tags" - schedule: - - cron: "0 0 * * 0" # weekly env: - BUILD_TAG: "build-engine-api:${{ github.run_number }}" - BUILD_NUMBER: ${{ github.run_number }} + BUILD_ENGINE_BUILD_TAG: "build-engine-api:${{ github.run_number }}" + OTEL_BUILD_TAG: "build-engine-otel:${{ github.run_number }}" jobs: - build: + check: + uses: "./.github/workflows/setup.yml" + secrets: + AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }} + push-to-ghcr: runs-on: ubuntu-latest - + needs: check + outputs: + DOCKER_TAG: ${{ steps.branch.outputs.DOCKER_TAG }} + ECS_CLUSTER: ${{ steps.branch.outputs.ECS_CLUSTER }} + BUILD_ENGINE_BUILD_TAG: ${{ env.BUILD_ENGINE_BUILD_TAG }} + OTEL_BUILD_TAG: ${{ env.OTEL_BUILD_TAG }} + if: ${{ success() && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') }} steps: - - uses: actions/checkout@v3 - - - name: Get environment info - run: | - echo Docker version - docker --version - echo - echo Env - env - - - name: Setup local.env - run: | - echo "COMPOSER_AUTH={\"github-oauth\":{\"github.com\":\""${{ secrets.GITHUB_TOKEN }}\""}}" > local.env - - - name: Install dependencies - run: | - echo "Installing ecs-deploy script..." - mkdir -p $HOME/.local/bin - curl -o $HOME/.local/bin/ecs-deploy https://raw.githubusercontent.com/silinternational/ecs-deploy/master/ecs-deploy - chmod +x $HOME/.local/bin/ecs-deploy - - - name: Tests - run: | - make test + - name: Checkout + uses: actions/checkout@v5 - - name: Build docker image - uses: docker/build-push-action@v4 + - name: Setup node + uses: actions/setup-node@v5 with: - push: false - tags: ${{ env.BUILD_TAG }} - context: . - load: true + node-version: 24 - name: Determine branch tag id: branch @@ -63,8 +40,15 @@ jobs: if [[ "${GITHUB_HEAD_REF}" != "" ]]; then BRANCH="${GITHUB_HEAD_REF}"; else BRANCH="${GITHUB_REF_NAME}"; fi case $BRANCH in develop) DOCKER_TAG="staging" ;; master) DOCKER_TAG="production" ;; *) DOCKER_TAG="${BRANCH//\//-}" ;; esac case $BRANCH in develop) ECS_CLUSTER="scriptoria-stg";; master) ECS_CLUSTER="scriptoria-prd" ;; *) ECS_CLUSTER="none" ;; esac - echo "DockerTag=${DOCKER_TAG}" >> $GITHUB_OUTPUT - echo "EcsCluster=${ECS_CLUSTER}" >> $GITHUB_OUTPUT + echo "DOCKER_TAG=${DOCKER_TAG}" >> $GITHUB_OUTPUT + echo "ECS_CLUSTER=${ECS_CLUSTER}" >> $GITHUB_OUTPUT + + - name: Build Docker images + run: | + echo "Building Docker images..." + docker build -t ${{ env.BUILD_ENGINE_BUILD_TAG}} . + docker build -t ${{ env.OTEL_BUILD_TAG}} -f Dockerfile.otel . + echo "Docker images built successfully." - name: Login to GitHub Container Registry uses: docker/login-action@v2 @@ -75,110 +59,54 @@ jobs: - name: Push to GHCR run: | - docker tag ${{ env.BUILD_TAG }} ghcr.io/sillsdev/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }} - docker push ghcr.io/sillsdev/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }} - - - name: Configure AWS credentials (SIL) - id: aws_sil - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.SIL__AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SIL__AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.SIL__AWS_DEFAULT_REGION }} - - - name: Login to AWS ECR (SIL) - id: ecr_sil - uses: aws-actions/amazon-ecr-login@v2 - with: - registries: ${{ secrets.SIL__AWS_ECR_ACCOUNT }} - - - name: Push to AWS ECR (SIL) - run: | - docker tag ${{ env.BUILD_TAG }} "${{ steps.ecr_sil.outputs.registry }}/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }}" - docker tag ${{ env.BUILD_TAG }} "${{ steps.ecr_sil.outputs.registry }}/appbuilder-buildengine-api:${{ env.BUILD_NUMBER }}" - docker push "${{ steps.ecr_sil.outputs.registry }}/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }}" - docker push "${{ steps.ecr_sil.outputs.registry }}/appbuilder-buildengine-api:${{ env.BUILD_NUMBER }}" - - - name: Deploy to ECS (SIL) - if: ${{ steps.branch.outputs.EcsCluster != 'none' }} - run: | - echo "Deploying ${{ env.BUILD_NUMBER }} to ${{ steps.branch.outputs.EcsCluster }}" - # Deploy to ECS cluster with service name 'build-engine', setting all images to the latest tag - ecs-deploy -c ${{ steps.branch.outputs.EcsCluster }} -n buildengine -i ignore -to ${{ env.BUILD_NUMBER }} --max-definitions 20 --timeout 600 - echo "Deployment initiated successfully." - - - name: Configure AWS credentials (FCBH) - if: false # Temporarily disabled - remove this line to re-enable - # if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-prd' }} # Restore this when re-enabling - id: aws_fcbh - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.FCBH__AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.FCBH__AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.FCBH__AWS_DEFAULT_REGION }} - - - name: Login to AWS ECR (FCBH) - if: false # Temporarily disabled - remove this line to re-enable - # if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-prd' }} # Restore this when re-enabling - id: ecr_fcbh - uses: aws-actions/amazon-ecr-login@v2 - with: - registries: ${{ secrets.FCBH__AWS_ECR_ACCOUNT }} - - - name: Push to AWS ECR (FCBH) - if: false # Temporarily disabled - remove this line to re-enable - # if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-prd' }} # Restore this when re-enabling - run: | - docker tag ${{ env.BUILD_TAG }} "${{ steps.ecr_fcbh.outputs.registry }}/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }}" - docker tag ${{ env.BUILD_TAG }} "${{ steps.ecr_fcbh.outputs.registry }}/appbuilder-buildengine-api:${{ env.BUILD_NUMBER }}" - docker push "${{ steps.ecr_fcbh.outputs.registry }}/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }}" - docker push "${{ steps.ecr_fcbh.outputs.registry }}/appbuilder-buildengine-api:${{ env.BUILD_NUMBER }}" - - - name: Deploy to ECS (FCBH) - if: false # Temporarily disabled - remove this line to re-enable - # if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-prd' }} # Restore this when re-enabling - run: | - echo "Deploying ${{ env.BUILD_NUMBER }} to ${{ steps.branch.outputs.EcsCluster }}" - # Deploy to ECS cluster with service name 'build-engine', setting all images to the latest tag - ecs-deploy -c ${{ steps.branch.outputs.EcsCluster }} -n buildengine -i ignore -to ${{ env.BUILD_NUMBER }} --max-definitions 20 --timeout 600 - echo "Deployment initiated successfully." - - - name: Configure AWS credentials (LU) - if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-stg' }} - id: aws_lu - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.LU__AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.LU__AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.LU__AWS_DEFAULT_REGION }} - - - name: Login to AWS ECR (LU) - if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-stg' }} - id: ecr_lu - uses: aws-actions/amazon-ecr-login@v2 - with: - registries: ${{ secrets.LU__AWS_ECR_ACCOUNT }} - - - name: Push to AWS ECR (LU) - if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-stg' }} - run: | - docker tag ${{ env.BUILD_TAG }} "${{ steps.ecr_lu.outputs.registry }}/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }}" - docker tag ${{ env.BUILD_TAG }} "${{ steps.ecr_lu.outputs.registry }}/appbuilder-buildengine-api:${{ env.BUILD_NUMBER }}" - docker push "${{ steps.ecr_lu.outputs.registry }}/appbuilder-buildengine-api:${{ steps.branch.outputs.DockerTag }}" - docker push "${{ steps.ecr_lu.outputs.registry }}/appbuilder-buildengine-api:${{ env.BUILD_NUMBER }}" - - - name: Deploy to ECS (LU) - if: ${{ steps.branch.outputs.EcsCluster == 'scriptoria-stg' }} - run: | - echo "Deploying ${{ env.BUILD_NUMBER }} to ${{ steps.branch.outputs.EcsCluster }}" - # Deploy to ECS cluster with service name 'build-engine', setting all images to the latest tag - ecs-deploy -c ${{ steps.branch.outputs.EcsCluster }} -n buildengine -i ignore -to ${{ env.BUILD_NUMBER }} --max-definitions 20 --timeout 600 - echo "Deployment initiated successfully." - - - name: Clean up older packages - uses: actions/delete-package-versions@v4 - with: - package-name: "appbuilder-buildengine-api" - package-type: "container" - min-versions-to-keep: 6 - delete-only-untagged-versions: "true" + docker tag ${{ env.BUILD_ENGINE_BUILD_TAG }} ghcr.io/sillsdev/appbuilder-buildengine-api:${{ steps.branch.outputs.DOCKER_TAG }} + docker push ghcr.io/sillsdev/appbuilder-buildengine-api:${{ steps.branch.outputs.DOCKER_TAG }} + + docker tag ${{ env.OTEL_BUILD_TAG }} ghcr.io/sillsdev/appbuilder-buildengine-otel:${{ steps.branch.outputs.DOCKER_TAG }} + docker push ghcr.io/sillsdev/appbuilder-buildengine-otel:${{ steps.branch.outputs.DOCKER_TAG }} + + deploy-sil: + needs: push-to-ghcr + uses: "./.github/workflows/deploy.yml" + with: + BUILD_NUMBER: ${{ github.run_number }} + ECS_CLUSTER: ${{ needs.push-to-ghcr.outputs.ECS_CLUSTER }} + DOCKER_TAG: ${{ needs.push-to-ghcr.outputs.DOCKER_TAG }} + BUILD_ENGINE_BUILD_TAG: ${{ needs.push-to-ghcr.outputs.BUILD_ENGINE_BUILD_TAG }} + OTEL_BUILD_TAG: ${{ needs.push-to-ghcr.outputs.OTEL_BUILD_TAG }} + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.SIL__AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.SIL__AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.SIL__AWS_DEFAULT_REGION }} + AWS_ECR_ACCOUNT: ${{ secrets.SIL__AWS_ECR_ACCOUNT }} + deploy-fcbh: + needs: push-to-ghcr + if: false # Temporarily disabled - remove this line to re-enable + # if: ${{ needs.push-to-ghcr.outputs.ECS_CLUSTER == 'scriptoria-prd' }} # Restore this when re-enabling + uses: "./.github/workflows/deploy.yml" + with: + BUILD_NUMBER: ${{ github.run_number }} + ECS_CLUSTER: ${{ needs.push-to-ghcr.outputs.ECS_CLUSTER }} + DOCKER_TAG: ${{ needs.push-to-ghcr.outputs.DOCKER_TAG }} + BUILD_ENGINE_BUILD_TAG: ${{ needs.push-to-ghcr.outputs.BUILD_ENGINE_BUILD_TAG }} + OTEL_BUILD_TAG: ${{ needs.push-to-ghcr.outputs.OTEL_BUILD_TAG }} + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.FCBH__AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.FCBH__AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.FCBH__AWS_DEFAULT_REGION }} + AWS_ECR_ACCOUNT: ${{ secrets.FCBH__AWS_ECR_ACCOUNT }} + deploy-lu: + needs: push-to-ghcr + if: ${{ needs.push-to-ghcr.outputs.ECS_CLUSTER == 'scriptoria-stg' }} + uses: "./.github/workflows/deploy.yml" + with: + BUILD_NUMBER: ${{ github.run_number }} + ECS_CLUSTER: ${{ needs.push-to-ghcr.outputs.ECS_CLUSTER }} + DOCKER_TAG: ${{ needs.push-to-ghcr.outputs.DOCKER_TAG }} + BUILD_ENGINE_BUILD_TAG: ${{ needs.push-to-ghcr.outputs.BUILD_ENGINE_BUILD_TAG }} + OTEL_BUILD_TAG: ${{ needs.push-to-ghcr.outputs.OTEL_BUILD_TAG }} + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.LU__AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LU__AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.LU__AWS_DEFAULT_REGION }} + AWS_ECR_ACCOUNT: ${{ secrets.LU__AWS_ECR_ACCOUNT }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..a35fe68 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,11 @@ +name: Test and Lint + +on: + pull_request: + branches: + - master + - develop + +jobs: + checks: + uses: ./.github/workflows/setup.yml diff --git a/.github/workflows/setup.yml b/.github/workflows/setup.yml new file mode 100644 index 0000000..fc7e844 --- /dev/null +++ b/.github/workflows/setup.yml @@ -0,0 +1,147 @@ +on: + workflow_call: + secrets: + AUTH0_SECRET: + required: false + +env: + APP_ENV: ci + +jobs: + # Install dependencies once and cache for other jobs + setup: + runs-on: ubuntu-latest + outputs: + BACKUP_AUTH0_SECRET: ${{ steps.set-vars.outputs.BACKUP_AUTH0_SECRET }} + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Get environment info + id: set-vars + run: | + echo Node version + node --version + npm --version + echo + echo Docker version + docker --version + BACKUP_AUTH0_SECRET=$(hexdump -vn32 -e'8/4 "%08x" 1 "\n"' /dev/urandom) + echo "BACKUP_AUTH0_SECRET=${BACKUP_AUTH0_SECRET}" >> $GITHUB_OUTPUT + + - name: Restore node_modules cache + id: restore-cache + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json', 'src/lib/prisma/schema.prisma') }} + + - name: Install dependencies + if: steps.restore-cache.outputs.cache-hit != 'true' + run: | + echo "Installing dependencies..." + npm ci + + - name: Cache node_modules + if: steps.restore-cache.outputs.cache-hit != 'true' + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json', 'src/lib/prisma/schema.prisma') }} + + # Type checking and linting + typecheck-lint: + runs-on: ubuntu-latest + needs: setup + env: + # Required for type checking. Leaving empty for now until needed for testing? + BUILD_ENGINE_ARTIFACTS_BUCKET: "" + AWS_ACCESS_KEY_ID: "" + AWS_SECRET_ACCESS_KEY: "" + BUILD_ENGINE_SECRETS_BUCKET: "" + SCRIPTURE_EARTH_KEY: "" + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + + - name: Restore node_modules cache + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json', 'src/lib/prisma/schema.prisma') }} + + - name: Run svelte-check + run: | + echo "Running svelte-check..." + npm run check + + - name: Run lint + run: | + echo "Running lint..." + npm run lint + + # Build and run a smoke test + build-and-test: + runs-on: ubuntu-latest + needs: setup + env: + CI: true + AUTH0_SECRET: ${{ secrets.AUTH0_SECRET || needs.setup.outputs.BACKUP_AUTH0_SECRET }} + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 24 + + - name: Restore node_modules cache + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json', 'src/lib/prisma/schema.prisma') }} + + - name: Build and seed database + run: | + echo "Building .env file..." + echo "AUTH0_SECRET=" >> .env + echo "Building the docker project..." + mkdir -p command-output + (./run ci build > command-output/build-output.txt 2>&1 || echo $? > command-output/build-exit-code.txt) & + echo "Beginning pull of images" + ./run ci pull valkey > /dev/null & + echo "Starting database..." + ./run ci up -d db + sleep 1 + echo "Resetting the database..." + npx prisma migrate reset -f --skip-seed --skip-generate + echo "Waiting for build to finish..." + wait + if [ -f command-output/build-exit-code.txt ]; then + BUILD_EXIT_CODE=$(cat command-output/build-exit-code.txt) + echo "Build failed with exit code $BUILD_EXIT_CODE" + cat command-output/build-output.txt + exit $BUILD_EXIT_CODE + fi + echo "Build completed." + env: + DATABASE_URL: 'postgresql://db-user:1234@localhost:5432/dev-buildengine?schema=public' + + - name: Start docker-compose services + run: | + echo "Starting docker-compose services..." + ./run ci up -d + + - name: Run tests + run: | + # Is the port open + sleep 1 + nc -zv localhost 8443 || { + echo "Port 8443 is not open" + ./run ci logs build-engine + exit 1 + } diff --git a/fixSourcemaps.cts b/fixSourcemaps.cts index 3b25d3e..4686871 100644 --- a/fixSourcemaps.cts +++ b/fixSourcemaps.cts @@ -14,9 +14,9 @@ const { opendir, readFile, writeFile } = require('node:fs/promises'); const fs = require('node:fs/promises'); const { join } = require('path'); -async function* walk(dir) { +async function* walk(dir: string): AsyncGenerator { for await (const file of await opendir(dir)) { - const path = join(dir, file.name); + const path: string = join(dir, file.name); if (file.isDirectory()) { yield* walk(path); } else { @@ -34,7 +34,7 @@ async function* walk(dir) { const content = await readFile(file, 'utf-8'); const json = JSON.parse(content); - json.sources = json.sources.map((source) => { + json.sources = json.sources.map((source: string) => { if (source.startsWith('../../../')) { return source.slice('../'.length); } diff --git a/package-lock.json b/package-lock.json index e0d5e66..1914833 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@aws-sdk/client-iam": "^3.911.0", "@aws-sdk/client-s3": "^3.907.0", "@aws-sdk/client-sts": "^3.907.0", + "@grpc/grpc-js": "^1.14.3", "@prisma/client": "^6.15.0", "bullmq-otel": "^1.1.1", "prisma": "^6.15.0", @@ -40,7 +41,7 @@ "@sveltejs/kit": "^2.22.0", "@sveltejs/vite-plugin-svelte": "^6.0.0", "@tailwindcss/vite": "^4.0.0", - "@types/node": "^24.6.0", + "@types/node": "^24.12.0", "bullmq": "^5.61.0", "daisyui": "^5.1.6", "eslint": "^9.18.0", @@ -3386,7 +3387,6 @@ "version": "1.14.3", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@grpc/proto-loader": "^0.8.0", @@ -3400,7 +3400,6 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", - "dev": true, "license": "Apache-2.0", "dependencies": { "lodash.camelcase": "^4.3.0", @@ -3595,7 +3594,6 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "dev": true, "license": "MIT", "funding": { "type": "opencollective", @@ -4393,35 +4391,30 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", @@ -4432,35 +4425,30 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@rollup/plugin-commonjs": { @@ -6343,13 +6331,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.6.0.tgz", - "integrity": "sha512-F1CBxgqwOMc4GKJ7eY22hWhBVQuMYTtqI8L0FcszYcpYX0fzfDGpez22Xau8Mgm7O9fI+zA/TYIdq3tGWfweBA==", - "dev": true, + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", "license": "MIT", "dependencies": { - "undici-types": "~7.13.0" + "undici-types": "~7.16.0" } }, "node_modules/@types/resolve": { @@ -6746,7 +6733,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6756,7 +6742,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -7216,7 +7201,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -7250,7 +7234,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -7263,7 +7246,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/commondir": { @@ -7612,7 +7594,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/empathic": { @@ -7851,7 +7832,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8539,7 +8519,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -9061,7 +9040,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9774,7 +9752,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, "license": "MIT" }, "node_modules/lodash.defaults": { @@ -9800,7 +9777,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "dev": true, "license": "Apache-2.0" }, "node_modules/luxon": { @@ -10663,7 +10639,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "dev": true, "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -10833,7 +10808,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11295,7 +11269,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -11369,7 +11342,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -11977,10 +11949,9 @@ } }, "node_modules/undici-types": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz", - "integrity": "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==", - "dev": true, + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, "node_modules/uri-js": { @@ -12253,7 +12224,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -12271,7 +12241,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -12304,7 +12273,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -12323,7 +12291,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" diff --git a/package.json b/package.json index 711549a..f0d2780 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@sveltejs/kit": "^2.22.0", "@sveltejs/vite-plugin-svelte": "^6.0.0", "@tailwindcss/vite": "^4.0.0", - "@types/node": "^24.6.0", + "@types/node": "^24.12.0", "bullmq": "^5.61.0", "daisyui": "^5.1.6", "eslint": "^9.18.0", @@ -60,12 +60,14 @@ "valibot": "^1.1.0", "vite": "^7.0.4" }, + "//grpc": "grpc is marked as a dependeny due to circular imports in libraries it depends on breaking 'sorcery'", "dependencies": { "@aws-sdk/client-codebuild": "^3.907.0", "@aws-sdk/client-ecr": "^3.981.0", "@aws-sdk/client-iam": "^3.911.0", "@aws-sdk/client-s3": "^3.907.0", "@aws-sdk/client-sts": "^3.907.0", + "@grpc/grpc-js": "^1.14.3", "@prisma/client": "^6.15.0", "bullmq-otel": "^1.1.1", "prisma": "^6.15.0", diff --git a/prisma.config.ts b/prisma.config.ts index 65f534f..c2b4968 100644 --- a/prisma.config.ts +++ b/prisma.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, env } from '@prisma/config'; +import { defineConfig } from '@prisma/config'; import path from 'path'; import 'dotenv/config'; @@ -6,8 +6,5 @@ export default defineConfig({ schema: path.join('src', 'lib', 'prisma', 'schema.prisma'), migrations: { path: path.join('src', 'lib', 'prisma', 'migrations') - }, - datasource: { - url: env('DATABASE_URL') } }); diff --git a/src/lib/prisma/schema.prisma b/src/lib/prisma/schema.prisma index c8a0f01..46eb730 100644 --- a/src/lib/prisma/schema.prisma +++ b/src/lib/prisma/schema.prisma @@ -4,6 +4,7 @@ generator client { datasource db { provider = "postgresql" + url = env("DATABASE_URL") } model build { diff --git a/src/lib/server/aws/s3.ts b/src/lib/server/aws/s3.ts index 0de0302..3c6aecf 100644 --- a/src/lib/server/aws/s3.ts +++ b/src/lib/server/aws/s3.ts @@ -15,12 +15,14 @@ import { S3SyncClient } from 's3-sync-client'; import { AWSVars } from './vars'; import { env } from '$env/dynamic/private'; import { - type BuildForPrefix, type ProviderForArtifacts, - type ProviderForPrefix, beginArtifacts, - getBasePrefixUrl, handleArtifact +} from '$lib/server/models/artifact-handle'; +import { + type BuildForPrefix, + type ProviderForPrefix, + getBasePrefixUrl } from '$lib/server/models/artifacts'; export class S3 { diff --git a/src/lib/server/job-executors/release.ts b/src/lib/server/job-executors/release.ts index c209bfc..b1cc46d 100644 --- a/src/lib/server/job-executors/release.ts +++ b/src/lib/server/job-executors/release.ts @@ -1,8 +1,8 @@ import type { Job } from 'bullmq'; import { readFile } from 'fs/promises'; import { CodeBuild } from '../aws/codebuild'; -import { AWSVars } from '../aws/vars'; import { S3 } from '../aws/s3'; +import { AWSVars } from '../aws/vars'; import { BullMQ, getQueues } from '../bullmq'; import { prisma } from '../prisma'; import { Build } from '$lib/server/models/build'; diff --git a/src/lib/server/models/artifact-handle.ts b/src/lib/server/models/artifact-handle.ts new file mode 100644 index 0000000..2fd5c2a --- /dev/null +++ b/src/lib/server/models/artifact-handle.ts @@ -0,0 +1,46 @@ +import type { Prisma } from '@prisma/client'; +import { Build } from './build'; +import { Release } from './release'; + +export type BuildForArtifacts = Prisma.buildGetPayload<{ + select: { id: true; artifact_url_base: true; artifact_files: true; version_code: true }; +}>; + +export type ReleaseForArtifacts = Prisma.releaseGetPayload<{ + select: { id: true; artifact_url_base: true; artifact_files: true }; +}>; + +export type ProviderForArtifacts = BuildForArtifacts | ReleaseForArtifacts; + +export function beginArtifacts(artifacts_provider: ProviderForArtifacts, baseUrl: string) { + artifacts_provider.artifact_url_base = baseUrl; + artifacts_provider.artifact_files = null; +} + +export function handleArtifact(provider: ProviderForArtifacts, key: string, contents: string = '') { + if ('version_code' in provider) { + const [type, name] = Build.artifactType(key); + if (type !== Build.Artifact.Unknown) { + if (provider.artifact_files) { + provider.artifact_files += ',' + name; + } else { + provider.artifact_files = name; + } + + const code = (contents && parseInt(contents)) || NaN; + + if (type === Build.Artifact.VersionCode && !isNaN(code)) { + provider.version_code = Number(contents); + } + } + } else { + const [type, name] = Release.artifactType(key); + if (type !== Release.Artifact.Unknown) { + if (provider.artifact_files) { + provider.artifact_files += ',' + name; + } else { + provider.artifact_files = name; + } + } + } +} diff --git a/src/lib/server/models/artifacts.ts b/src/lib/server/models/artifacts.ts index 9e4558f..43eb92a 100644 --- a/src/lib/server/models/artifacts.ts +++ b/src/lib/server/models/artifacts.ts @@ -1,6 +1,4 @@ import type { Prisma } from '@prisma/client'; -import { Build } from './build'; -import { Release } from './release'; export function getArtifactUrl( pattern: RegExp, @@ -56,44 +54,3 @@ export function getBasePrefixUrl(artifacts_provider: ProviderForPrefix, productS : getArtifactPath(artifacts_provider.job, productStage); return `${artifactPath}/${artifacts_provider.id}`; } - -export type BuildForArtifacts = Prisma.buildGetPayload<{ - select: { id: true; artifact_url_base: true; artifact_files: true; version_code: true }; -}>; - -export type ReleaseForArtifacts = Prisma.releaseGetPayload<{ - select: { id: true; artifact_url_base: true; artifact_files: true }; -}>; - -export type ProviderForArtifacts = BuildForArtifacts | ReleaseForArtifacts; - -export function beginArtifacts(artifacts_provider: ProviderForArtifacts, baseUrl: string) { - artifacts_provider.artifact_url_base = baseUrl; - artifacts_provider.artifact_files = null; -} - -export function handleArtifact(provider: ProviderForArtifacts, key: string, contents: string = '') { - if ('version_code' in provider) { - const [type, name] = Build.artifactType(key); - if (type !== Build.Artifact.Unknown) { - if (provider.artifact_files) { - provider.artifact_files += ',' + name; - } else { - provider.artifact_files = name; - } - - if (type === Build.Artifact.VersionCode) { - provider.version_code = Number(contents); - } - } - } else { - const [type, name] = Release.artifactType(key); - if (type !== Release.Artifact.Unknown) { - if (provider.artifact_files) { - provider.artifact_files += ',' + name; - } else { - provider.artifact_files = name; - } - } - } -}