diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f06c4a959c..eff6805721 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,8 @@ permissions: packages: write issues: write pull-requests: write + actions: write + id-token: write jobs: core: @@ -76,6 +78,14 @@ jobs: core_cache_key: ${{ needs.core.outputs.cache_key }} core_cache_path: ${{ needs.core.outputs.cache_path }} + login-quality: + uses: ./.github/workflows/login-quality.yml + permissions: + actions: write + id-token: write + with: + force: ${{ github.event_name == 'workflow_dispatch' }} + container: needs: [compile] uses: ./.github/workflows/container.yml @@ -86,6 +96,10 @@ jobs: with: build_image_name: "ghcr.io/zitadel/zitadel-build" + login-container: + uses: ./.github/workflows/login-container.yml + if: ${{ github.event_name == 'workflow_dispatch' }} + e2e: uses: ./.github/workflows/e2e.yml needs: [compile] @@ -98,7 +112,7 @@ jobs: issues: write pull-requests: write needs: - [version, core-unit-test, core-integration-test, lint, container, e2e] + [version, core-unit-test, core-integration-test, lint, container, e2e, login-container] if: ${{ github.event_name == 'workflow_dispatch' }} secrets: GCR_JSON_KEY_BASE64: ${{ secrets.GCR_JSON_KEY_BASE64 }} @@ -109,3 +123,6 @@ jobs: semantic_version: "23.0.7" image_name: "ghcr.io/zitadel/zitadel" google_image_name: "europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel" + build_image_name_login: ${{ needs.login-container.outputs.login_build_image }} + image_name_login: "ghcr.io/zitadel/login" + google_image_name_login: europe-docker.pkg.dev/zitadel-common/zitadel-repo/login diff --git a/.github/workflows/login-container.yml b/.github/workflows/login-container.yml new file mode 100644 index 0000000000..82a9a17389 --- /dev/null +++ b/.github/workflows/login-container.yml @@ -0,0 +1,45 @@ +name: Login Container + +on: + workflow_call: + outputs: + login_build_image: + description: 'The image name of the built production standalone login image' + value: ${{ jobs.login-container.outputs.login_build_image }} + +jobs: + login-container: + name: Build Login Container + runs-on: depot-ubuntu-22.04-8 + permissions: + id-token: write + outputs: + login_build_image: ${{ steps.get-login-tag.outputs.LOGIN_TAG }} + steps: + - uses: actions/checkout@v4 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/zitadel/login + tags: | + type=raw,value=latest,enable={{is_default_branch}} + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + - uses: depot/setup-action@v1 + with: + oidc: true + - name: Build Login Container + run: make login-standalone-build + env: + # latest if branch is main, otherwise image version which is the pull request number + BAKE_CLI: depot bake + DEPOT_PROJECT_ID: w47wkxzdtw + FORCE: ${{ github.event.inputs.force }} + - name: Get Login image tag + id: get-login-tag + run: echo "LOGIN_TAG=$(make login-standalone-build-tag)" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/login-quality.yml b/.github/workflows/login-quality.yml new file mode 100644 index 0000000000..bbeda75c43 --- /dev/null +++ b/.github/workflows/login-quality.yml @@ -0,0 +1,64 @@ +name: Login Quality + +on: + workflow_call: + inputs: + force: + description: 'Ignore run caches' + type: boolean + required: true + outputs: + login_build_image: + description: 'The image name of the built production standalone login image' + value: 'ghcr.io/zitadel/login:${{ github.sha }}' + +jobs: + quality: + name: Ensure Quality + runs-on: depot-ubuntu-22.04-8 + timeout-minutes: 30 + permissions: + id-token: write + actions: write + env: + CACHE_DIR: /tmp/login-run-caches + steps: + - uses: actions/checkout@v4 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/zitadel/login + tags: | + type=raw,value=latest,enable={{is_default_branch}} + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + - uses: depot/setup-action@v1 + with: + oidc: true + - name: Restore Run Caches + uses: actions/cache/restore@v4 + id: run-caches-restore + with: + path: ${{ env.CACHE_DIR }} + key: ${{ runner.os }}-login-run-caches-${{github.ref_name}}-${{ github.sha }}-${{github.run_attempt}} + restore-keys: | + ${{ runner.os }}-login-run-caches-${{github.ref_name}}-${{ github.sha }}- + ${{ runner.os }}-login-run-caches-${{github.ref_name}}- + ${{ runner.os }}-login-run-caches- + - run: make login-quality + env: + # latest if branch is main, otherwise image version which is the pull request number + LOGIN_BAKE_CLI: depot bake + DEPOT_PROJECT_ID: w47wkxzdtw + FORCE: ${{ github.event.inputs.force }} + - name: Save Run Caches + uses: actions/cache/save@v4 + with: + path: ${{ env.CACHE_DIR }} + key: ${{ steps.run-caches-restore.outputs.cache-primary-key }} + if: always() diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e40ae8805..8a6cb54ffb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,15 @@ on: google_image_name: required: true type: string + build_image_name_login: + required: true + type: string + image_name_login: + required: true + type: string + google_image_name_login: + required: true + type: string secrets: GCR_JSON_KEY_BASE64: description: 'base64 endcrypted key to connect to Google' @@ -96,6 +105,9 @@ jobs: docker buildx imagetools create \ --tag ${{ inputs.google_image_name }}:${{ needs.version.outputs.version }} \ ${{ inputs.build_image_name }} + docker buildx imagetools create \ + --tag ${{ inputs.google_image_name_login }}:${{ needs.version.outputs.version }} \ + ${{ inputs.build_image_name_login }} - name: Publish latest if: ${{ github.ref_name == 'next' }} @@ -106,6 +118,9 @@ jobs: docker buildx imagetools create \ --tag ${{ inputs.image_name }}:latest-debug \ ${{ inputs.build_image_name }}-debug + docker buildx imagetools create \ + --tag ${{ inputs.image_name_login }}:latest \ + ${{ inputs.build_image_name_login }} homebrew-tap: runs-on: ubuntu-22.04 @@ -146,3 +161,42 @@ jobs: GH_TOKEN: ${{ steps.generate-token.outputs.token }} run: | gh workflow -R zitadel/zitadel-charts run bump.yml + + typescript-packages: + runs-on: ubuntu-latest + needs: version + if: ${{ github.ref_name == 'next' }} + continue-on-error: true + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install pnpm + uses: pnpm/action-setup@v4 + + - name: Install dependencies + working-directory: login + run: pnpm install + + - name: Create Release Pull Request + uses: changesets/action@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + version: echo -n "${{ needs.version.outputs.version }}" + cwd: login + + typescript-repo: + runs-on: ubuntu-latest + if: ${{ github.ref_name == 'next' }} + continue-on-error: true + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Push Subtree + run: make login-push diff --git a/Makefile b/Makefile index 3c50231bee..7825b2cf35 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,10 @@ ZITADEL_MASTERKEY ?= MasterkeyNeedsToHave32Characters export GOCOVERDIR ZITADEL_MASTERKEY +LOGIN_REMOTE_NAME := login +LOGIN_REMOTE_URL ?= https://github.com/zitadel/typescript.git +LOGIN_REMOTE_BRANCH ?= main + .PHONY: compile compile: core_build console_build compile_pipeline @@ -165,3 +169,20 @@ core_lint: --config ./.golangci.yaml \ --out-format=github-actions \ --concurrency=$$(getconf _NPROCESSORS_ONLN) + +.PHONY: login-pull +login-pull: login-ensure-remote + git fetch $(LOGIN_REMOTE_NAME) + git subtree pull --prefix=login $(LOGIN_REMOTE_NAME) $(LOGIN_REMOTE_BRANCH) + +.PHONY: login-push +login-push: login-ensure-remote + git subtree push --prefix=login $(LOGIN_REMOTE_NAME) $(LOGIN_REMOTE_BRANCH) + +login-ensure-remote: + @git remote -v | grep $(LOGIN_REMOTE_NAME) || \ + git remote add $(LOGIN_REMOTE_NAME) $(LOGIN_REMOTE_URL) + +export LOGIN_DIR := ./login/ +export LOGIN_BAKE_CLI_ADDITIONAL_ARGS := --set login-*.context=./login/ --file ./docker-bake.hcl +include login/Makefile diff --git a/docker-bake.hcl b/docker-bake.hcl new file mode 100644 index 0000000000..466e7a8c4e --- /dev/null +++ b/docker-bake.hcl @@ -0,0 +1,14 @@ +target "typescript-proto-client" { + contexts = { + proto-files = "target:proto-files" + } + output = [ + "type=local,dest=login/packages/zitadel-proto" + ] +} + +target "typescript-proto-client-out" { + output = [ + "type=local,dest=login/packages/zitadel-proto" + ] +} diff --git a/dockerfiles/proto-files.Dockerfile b/dockerfiles/proto-files.Dockerfile new file mode 100644 index 0000000000..0af3346096 --- /dev/null +++ b/dockerfiles/proto-files.Dockerfile @@ -0,0 +1,8 @@ +FROM bufbuild/buf:1.54.0 AS proto-files +RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto-files && \ + buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto-files && \ + buf export https://github.com/googleapis/googleapis.git --path google/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto-files + +FROM scratch +COPY --from=proto-files /proto-files / +COPY ./proto / diff --git a/dockerfiles/proto-files.Dockerfile.dockerignore b/dockerfiles/proto-files.Dockerfile.dockerignore new file mode 100644 index 0000000000..e26cd3c2d6 --- /dev/null +++ b/dockerfiles/proto-files.Dockerfile.dockerignore @@ -0,0 +1,2 @@ +* +!proto diff --git a/dockerfiles/typescript-proto-client.Dockerfile b/dockerfiles/typescript-proto-client.Dockerfile new file mode 100644 index 0000000000..807ef4359c --- /dev/null +++ b/dockerfiles/typescript-proto-client.Dockerfile @@ -0,0 +1,14 @@ +FROM login-pnpm AS typescript-proto-client +COPY ./login/packages/zitadel-proto/package.json ./packages/zitadel-proto/ +RUN --mount=type=cache,id=pnpm,target=/pnpm/store \ + pnpm install --frozen-lockfile --workspace-root --filter zitadel-proto +COPY --from=proto-files /buf.yaml /buf.lock /proto-files/ +COPY --from=proto-files /zitadel /proto-files/zitadel +COPY ./login/packages/zitadel-proto/buf.gen.yaml ./packages/zitadel-proto/ +RUN ls /proto-files && cd packages/zitadel-proto && pnpm exec buf generate /proto-files + +FROM scratch AS typescript-proto-client-out +COPY --from=typescript-proto-client /build/packages/zitadel-proto/zitadel /zitadel +COPY --from=typescript-proto-client /build/packages/zitadel-proto/google /google +COPY --from=typescript-proto-client /build/packages/zitadel-proto/protoc-gen-openapiv2 /protoc-gen-openapiv2 +COPY --from=typescript-proto-client /build/packages/zitadel-proto/validate /validate diff --git a/dockerfiles/typescript-proto-client.Dockerfile.dockerignore b/dockerfiles/typescript-proto-client.Dockerfile.dockerignore new file mode 100644 index 0000000000..2d7f6be262 --- /dev/null +++ b/dockerfiles/typescript-proto-client.Dockerfile.dockerignore @@ -0,0 +1,3 @@ +* +!login/packages/zitadel-proto/ +login/packages/zitadel-proto/proto