Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 98e5e1891a | |||
| 06343e6ed3 | |||
| 82a3b612ec | |||
| 1e549d3fc2 | |||
| 55126f4af6 | |||
| cca49f2292 | |||
| 23f8296659 | |||
| 9abed01e53 | |||
| 3b1aba9672 | |||
| 22061486a8 | |||
| 38785ccf92 | |||
| 1f78a4a079 | |||
| 20fa33abeb | |||
| 16a9c73624 | |||
| b358ef6686 | |||
| ac9c7a81c3 | |||
| e800d0c16c | |||
| d8bbe57b17 | |||
| 168657bd14 | |||
| 6d49db5081 | |||
| 9a6ade0d96 | |||
| a6e9b55837 | |||
| 356f6ad76f | |||
| fbdebec6c8 | |||
| 10fccc17f7 | |||
| 0cf7b27f89 | |||
| 0ac2ca73ec | |||
| 7b67a2f758 | |||
| 8b86145519 | |||
| ac7a8dd90e | |||
| 6903b7f768 | |||
| 2e8b8d7330 | |||
| b4d5375954 |
26
.gitea/actions/get-build-options/action.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: "Get Build Options"
|
||||||
|
description: "Sanitizies and unifies the environment into build options"
|
||||||
|
outputs:
|
||||||
|
short-sha:
|
||||||
|
description: "Shortened hash if the current commit"
|
||||||
|
build-arch:
|
||||||
|
description: "Docker-compatible representation of build arch"
|
||||||
|
build-platform:
|
||||||
|
description: "Docker-compatible representation of build platform"
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: "Compute Build Options"
|
||||||
|
shell: "bash"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
SHORT_SHA="${GITHUB_SHA::8}"
|
||||||
|
BUILD_ARCH="amd64"
|
||||||
|
BUILD_PLATFORM="linux/amd64"
|
||||||
|
if [ "${RUNNER_ARCH}" = "ARM64" ];then
|
||||||
|
BUILD_ARCH="arm64"
|
||||||
|
BUILD_PLATFORM="linux/arm64"
|
||||||
|
fi
|
||||||
|
echo "short-sha=$SHORT_SHA" >> $GITHUB_OUTPUT
|
||||||
|
echo "build-arch=$BUILD_ARCH" >> $GITHUB_OUTPUT
|
||||||
|
echo "build-platform=$BUILD_PLATFORM" >> $GITHUB_OUTPUT
|
||||||
17
.gitea/actions/get-run-info/action.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
name: "Get Run Info"
|
||||||
|
description: "Sanitizies and unifies the environment into run info"
|
||||||
|
inputs:
|
||||||
|
compose-project-base:
|
||||||
|
description: "Base for the Compose project"
|
||||||
|
required: true
|
||||||
|
outputs:
|
||||||
|
compose-project:
|
||||||
|
description: "Compose project name"
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: "Compute Run Info"
|
||||||
|
shell: "bash"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
echo "compose-project=${{ inputs.compose-project-base }}-${GITHUB_RUN_NUMBER}" >> $GITHUB_OUTPUT
|
||||||
27
.gitea/actions/get-service-version/action.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: "Get Run Info"
|
||||||
|
description: "Sanitizies and unifies the environment into run info"
|
||||||
|
inputs:
|
||||||
|
service:
|
||||||
|
description: "The service to work on"
|
||||||
|
required: true
|
||||||
|
outputs:
|
||||||
|
version:
|
||||||
|
description: "Service version"
|
||||||
|
build-number:
|
||||||
|
description: "Build number"
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: "Compute Service Version"
|
||||||
|
shell: "bash"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
if [[ ! -z "${GITHUB_HEAD_REF}" || "${GITHUB_REF_NAME}" = "development" ]]; then
|
||||||
|
VERSION="${GITHUB_SHA::8}"
|
||||||
|
BUILD="${GITHUB_RUN_NUMBER}"
|
||||||
|
else
|
||||||
|
VERSION="v$(grep -Po '(?<=^version\s=\s")[^"]+' services/${{ inputs.service }}/pyproject.toml)"
|
||||||
|
BUILD="01"
|
||||||
|
fi
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "build-number=$BUILD" >> $GITHUB_OUTPUT
|
||||||
19
.gitea/actions/setup-ansible/action.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name: "Set up Ansible"
|
||||||
|
description: "Downloads and installs Ansible"
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "Ansible version to install"
|
||||||
|
required: false
|
||||||
|
default: "10.2.0"
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: "Install Ansible"
|
||||||
|
shell: "bash"
|
||||||
|
env:
|
||||||
|
PIP_INDEX_URL: "https://nexus.bthlabs.pl/repository/pypi/simple/"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
python3 -m venv /opt/ansible
|
||||||
|
|
||||||
|
/opt/ansible/bin/pip install ansible==${{ inputs.version }}
|
||||||
32
.gitea/actions/setup-k8s/action.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: "Set up k8s"
|
||||||
|
description: "Downloads and installs k8s tools"
|
||||||
|
inputs:
|
||||||
|
arch:
|
||||||
|
description: "Architecture"
|
||||||
|
required: true
|
||||||
|
kubectl-version:
|
||||||
|
description: "kubectl version to install"
|
||||||
|
required: false
|
||||||
|
default: "1.33.4"
|
||||||
|
kustomize-version:
|
||||||
|
description: "kustomize version to install"
|
||||||
|
required: false
|
||||||
|
default: "5.7.1"
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: "Install k8s tools"
|
||||||
|
shell: "bash"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
mkdir -p /opt/k8s/bin /opt/k8s/etc /opt/k8s/src
|
||||||
|
|
||||||
|
wget -O /opt/k8s/src/kubectl "https://nexus.bthlabs.pl/repository/ops-tools/k8s/kubectl-${{ inputs.kubectl-version }}-linux-${{ inputs.arch }}"
|
||||||
|
chmod a+x /opt/k8s/src/kubectl
|
||||||
|
mv /opt/k8s/src/kubectl /opt/k8s/bin
|
||||||
|
|
||||||
|
wget -O /opt/k8s/src/kustomize "https://nexus.bthlabs.pl/repository/ops-tools/k8s/kustomize-${{ inputs.kustomize-version }}-linux-${{ inputs.arch }}"
|
||||||
|
chmod a+x /opt/k8s/src/kustomize
|
||||||
|
mv /opt/k8s/src/kustomize /opt/k8s/bin
|
||||||
|
|
||||||
|
rm -rf /opt/k8s/src/
|
||||||
28
.gitea/tools/render-docker-compose-ci.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
set +x
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
cat >"./docker-compose-ci-${COMPOSE_PROJECT}.yaml" <<EOF
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/postgres:15.13-${COMPOSE_PROJECT}"
|
||||||
|
|
||||||
|
keycloak:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/keycloak:22.0.3-${COMPOSE_PROJECT}"
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/rabbitmq:3.10.8-${COMPOSE_PROJECT}"
|
||||||
|
|
||||||
|
apple-ci:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/apple:ci-${COMPOSE_PROJECT}"
|
||||||
|
|
||||||
|
backend-ci:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:ci-${COMPOSE_PROJECT}"
|
||||||
|
|
||||||
|
extension-ci:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/extension:ci-${COMPOSE_PROJECT}"
|
||||||
|
|
||||||
|
packages-ci:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/packages:ci-${COMPOSE_PROJECT}"
|
||||||
|
EOF
|
||||||
83
.gitea/workflows/build-deployment-images.yaml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
name: "Build deployment images"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
target:
|
||||||
|
required: true
|
||||||
|
type: "string"
|
||||||
|
registry:
|
||||||
|
required: false
|
||||||
|
type: "string"
|
||||||
|
default: "docker-hosted.nexus.bthlabs.pl"
|
||||||
|
platform:
|
||||||
|
required: false
|
||||||
|
type: "string"
|
||||||
|
default: "linux/amd64,linux/arm64"
|
||||||
|
secrets:
|
||||||
|
VAULT_ROLE_ID:
|
||||||
|
required: true
|
||||||
|
VAULT_SECRET_ID:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-deployment-images:
|
||||||
|
name: "Build deployment images"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- name: "Checkout the code"
|
||||||
|
uses: "actions/checkout@v2"
|
||||||
|
- name: "Get build options"
|
||||||
|
id: "get-build-options"
|
||||||
|
uses: "./.gitea/actions/get-build-options"
|
||||||
|
- name: "Get `backend` version"
|
||||||
|
id: "get-backend-version"
|
||||||
|
uses: "./.gitea/actions/get-service-version"
|
||||||
|
with:
|
||||||
|
service: "backend"
|
||||||
|
- name: "Import Secrets"
|
||||||
|
id: "import-secrets"
|
||||||
|
uses: "hashicorp/vault-action@v2"
|
||||||
|
with:
|
||||||
|
url: "https://vault.bthlabs.pl/"
|
||||||
|
method: "approle"
|
||||||
|
roleId: "${{ secrets.VAULT_ROLE_ID }}"
|
||||||
|
secretId: "${{ secrets.VAULT_SECRET_ID }}"
|
||||||
|
secrets: |
|
||||||
|
gitea/data/${{ inputs.registry }} username | DOCKER_USERNAME ;
|
||||||
|
gitea/data/${{ inputs.registry }} password | DOCKER_PASSWORD
|
||||||
|
- name: "Set up Docker Buildx"
|
||||||
|
id: "setup-docker-buildx"
|
||||||
|
uses: "docker/setup-buildx-action@v3"
|
||||||
|
with:
|
||||||
|
driver: "remote"
|
||||||
|
endpoint: "tcp://builder-01.bthlab:2375"
|
||||||
|
platforms: "linux/amd64"
|
||||||
|
append: |
|
||||||
|
- endpoint: "tcp://builder-mac-01.bthlab:2375"
|
||||||
|
platforms: "linux/arm64"
|
||||||
|
- name: "Login to Docker Registry"
|
||||||
|
uses: "docker/login-action@v3"
|
||||||
|
with:
|
||||||
|
registry: "${{ inputs.registry }}"
|
||||||
|
username: "${{ steps.import-secrets.outputs.DOCKER_USERNAME }}"
|
||||||
|
password: "${{ steps.import-secrets.outputs.DOCKER_PASSWORD }}"
|
||||||
|
- name: "Build `backend-aio` image"
|
||||||
|
env:
|
||||||
|
SHORT_SHA: "${{ steps.get-build-options.outputs.short-sha }}"
|
||||||
|
VERSION: "${{ steps.get-backend-version.outputs.version }}"
|
||||||
|
BUILD: "${{ steps.get-backend-version.outputs.build-number }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
docker buildx build \
|
||||||
|
--cache-from "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket" \
|
||||||
|
--cache-to "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,target=max" \
|
||||||
|
--push \
|
||||||
|
--platform "${{ inputs.platform }}" \
|
||||||
|
--build-arg IMAGE_ID="${{ inputs.target }}.${SHORT_SHA}" \
|
||||||
|
--build-arg IMAGE_VERSION="${VERSION}" \
|
||||||
|
--build-arg IMAGE_REVISION="${SHORT_SHA}" \
|
||||||
|
-f services/backend/Dockerfile \
|
||||||
|
--target "${{ inputs.target }}" \
|
||||||
|
-t "${{ inputs.registry }}/hotpocket/backend:${{ inputs.target }}-${VERSION}-${BUILD}" \
|
||||||
|
services/
|
||||||
@@ -17,8 +17,24 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: "Checkout the code"
|
- name: "Checkout the code"
|
||||||
uses: "actions/checkout@v2"
|
uses: "actions/checkout@v2"
|
||||||
|
- name: "Get run info"
|
||||||
|
id: "get-run-info"
|
||||||
|
uses: "./.gitea/actions/get-run-info"
|
||||||
|
with:
|
||||||
|
compose-project-base: "${{ vars.COMPOSE_PROJECT_BASE }}"
|
||||||
|
- name: "Get build options"
|
||||||
|
id: "get-build-options"
|
||||||
|
uses: "./.gitea/actions/get-build-options"
|
||||||
- name: "Set up Docker Buildx"
|
- name: "Set up Docker Buildx"
|
||||||
|
id: "setup-docker-buildx"
|
||||||
uses: "docker/setup-buildx-action@v3"
|
uses: "docker/setup-buildx-action@v3"
|
||||||
|
with:
|
||||||
|
driver: "remote"
|
||||||
|
endpoint: "tcp://builder-01.bthlab:2375"
|
||||||
|
platforms: "linux/amd64"
|
||||||
|
append: |
|
||||||
|
- endpoint: "tcp://builder-mac-01.bthlab:2375"
|
||||||
|
platforms: "linux/arm64"
|
||||||
- name: "Build `postgres` image"
|
- name: "Build `postgres` image"
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@@ -26,7 +42,10 @@ jobs:
|
|||||||
context: "services/"
|
context: "services/"
|
||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/postgres:15.13-local"
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/postgres:15.13-${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
platforms: "${{ steps.get-build-options.outputs.build-platform }}"
|
||||||
|
cache-from: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket"
|
||||||
|
cache-to: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,mode=max"
|
||||||
- name: "Build `keycloak` image"
|
- name: "Build `keycloak` image"
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@@ -34,7 +53,10 @@ jobs:
|
|||||||
context: "services/"
|
context: "services/"
|
||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/keycloak:22.0.3-local"
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/keycloak:22.0.3-${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
platforms: "${{ steps.get-build-options.outputs.build-platform }}"
|
||||||
|
cache-from: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket"
|
||||||
|
cache-to: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,mode=max"
|
||||||
- name: "Build `rabbitmq` image"
|
- name: "Build `rabbitmq` image"
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@@ -42,7 +64,10 @@ jobs:
|
|||||||
context: "services/"
|
context: "services/"
|
||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/rabbitmq:3.10.8-local"
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/rabbitmq:3.10.8-${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
platforms: "${{ steps.get-build-options.outputs.build-platform }}"
|
||||||
|
cache-from: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket"
|
||||||
|
cache-to: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,mode=max"
|
||||||
- name: "Build `backend-ci` image"
|
- name: "Build `backend-ci` image"
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@@ -51,7 +76,10 @@ jobs:
|
|||||||
target: "ci"
|
target: "ci"
|
||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:ci-local"
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:ci-${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
platforms: "${{ steps.get-build-options.outputs.build-platform }}"
|
||||||
|
cache-from: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket"
|
||||||
|
cache-to: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,mode=max"
|
||||||
- name: "Build `packages-ci` image"
|
- name: "Build `packages-ci` image"
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@@ -60,7 +88,10 @@ jobs:
|
|||||||
target: "ci"
|
target: "ci"
|
||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/packages:ci-local"
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/packages:ci-${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
platforms: "${{ steps.get-build-options.outputs.build-platform }}"
|
||||||
|
cache-from: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket"
|
||||||
|
cache-to: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,mode=max"
|
||||||
- name: "Build `extension-ci` image"
|
- name: "Build `extension-ci` image"
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
@@ -69,23 +100,91 @@ jobs:
|
|||||||
target: "ci"
|
target: "ci"
|
||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/extension:ci-local"
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/extension:ci-${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
platforms: "${{ steps.get-build-options.outputs.build-platform }}"
|
||||||
|
cache-from: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket"
|
||||||
|
cache-to: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,mode=max"
|
||||||
|
- name: "Build `apple-ci` image"
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
file: "services/apple/Dockerfile"
|
||||||
|
context: "services/"
|
||||||
|
target: "ci"
|
||||||
|
push: false
|
||||||
|
load: true
|
||||||
|
tags: "docker-hosted.nexus.bthlabs.pl/hotpocket/apple:ci-${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
platforms: "${{ steps.get-build-options.outputs.build-platform }}"
|
||||||
|
cache-from: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket"
|
||||||
|
cache-to: "type=registry,ref=nexus.bthlab.bthlabs.net:8001/hotpocket,mode=max"
|
||||||
|
- name: "Prepare the build"
|
||||||
|
id: "prepare"
|
||||||
|
env:
|
||||||
|
COMPOSE_PROJECT: "${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
./.gitea/tools/render-docker-compose-ci.sh
|
||||||
- name: "Run `backend` checks"
|
- name: "Run `backend` checks"
|
||||||
|
if: "steps.prepare.conclusion == 'success'"
|
||||||
|
env:
|
||||||
|
COMPOSE_PROJECT: "${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm backend-ci inv ci
|
docker compose \
|
||||||
|
-p "${COMPOSE_PROJECT}" \
|
||||||
|
-f "docker-compose.yaml" \
|
||||||
|
-f "docker-compose-ci.yaml" \
|
||||||
|
-f "docker-compose-ci-${COMPOSE_PROJECT}.yaml" \
|
||||||
|
run --rm \
|
||||||
|
backend-ci inv ci
|
||||||
- name: "Run `packages` checks"
|
- name: "Run `packages` checks"
|
||||||
if: always()
|
if: "steps.prepare.conclusion == 'success'"
|
||||||
|
env:
|
||||||
|
COMPOSE_PROJECT: "${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm packages-ci inv ci
|
docker compose \
|
||||||
|
-p "${COMPOSE_PROJECT}" \
|
||||||
|
-f "docker-compose.yaml" \
|
||||||
|
-f "docker-compose-ci.yaml" \
|
||||||
|
-f "docker-compose-ci-${COMPOSE_PROJECT}.yaml" \
|
||||||
|
run --rm \
|
||||||
|
packages-ci inv ci
|
||||||
- name: "Run `extension` checks"
|
- name: "Run `extension` checks"
|
||||||
if: always()
|
if: "steps.prepare.conclusion == 'success'"
|
||||||
|
env:
|
||||||
|
COMPOSE_PROJECT: "${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml run --rm extension-ci inv ci
|
docker compose \
|
||||||
|
-p "${COMPOSE_PROJECT}" \
|
||||||
|
-f "docker-compose.yaml" \
|
||||||
|
-f "docker-compose-ci.yaml" \
|
||||||
|
-f "docker-compose-ci-${COMPOSE_PROJECT}.yaml" \
|
||||||
|
run --rm \
|
||||||
|
extension-ci inv ci
|
||||||
|
- name: "Run `apple` checks"
|
||||||
|
if: "steps.prepare.conclusion == 'success'"
|
||||||
|
env:
|
||||||
|
COMPOSE_PROJECT: "${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
docker compose \
|
||||||
|
-p "${COMPOSE_PROJECT}" \
|
||||||
|
-f "docker-compose.yaml" \
|
||||||
|
-f "docker-compose-ci.yaml" \
|
||||||
|
-f "docker-compose-ci-${COMPOSE_PROJECT}.yaml" \
|
||||||
|
run --rm \
|
||||||
|
apple-ci inv ci
|
||||||
- name: "Clean up"
|
- name: "Clean up"
|
||||||
if: always()
|
if: always()
|
||||||
|
env:
|
||||||
|
COMPOSE_PROJECT: "${{ steps.get-run-info.outputs.compose-project }}"
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
docker compose -f docker-compose.yaml -f docker-compose-ci.yaml down --volumes
|
docker compose \
|
||||||
|
-p "${COMPOSE_PROJECT}" \
|
||||||
|
-f "docker-compose.yaml" \
|
||||||
|
-f "docker-compose-ci.yaml" \
|
||||||
|
-f "docker-compose-ci-${COMPOSE_PROJECT}.yaml" \
|
||||||
|
down --volumes --rmi all || true
|
||||||
|
rm -f "docker-compose-ci-${COMPOSE_PROJECT}.yaml" || true
|
||||||
|
|||||||
91
.gitea/workflows/development.yaml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
name: "Development deployment"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "development"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-for-development:
|
||||||
|
name: "Build"
|
||||||
|
uses: "./.gitea/workflows/build-deployment-images.yaml"
|
||||||
|
with:
|
||||||
|
target: "deployment"
|
||||||
|
platform: "linux/amd64"
|
||||||
|
registry: "nexus.bthlab.bthlabs.net:8002"
|
||||||
|
secrets:
|
||||||
|
VAULT_ROLE_ID: "${{ secrets.VAULT_ROLE_ID }}"
|
||||||
|
VAULT_SECRET_ID: "${{ secrets.VAULT_SECRET_ID }}"
|
||||||
|
|
||||||
|
deploy-to-deployment:
|
||||||
|
name: "Deploy"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
needs:
|
||||||
|
- "build-for-development"
|
||||||
|
env:
|
||||||
|
KUBERNETES_NAMESPACE: "hotpocket-development"
|
||||||
|
KUBERNETES_CLUSTER: "k8s.bthlab"
|
||||||
|
steps:
|
||||||
|
- name: "Checkout the code"
|
||||||
|
uses: "actions/checkout@v2"
|
||||||
|
- name: "Get build options"
|
||||||
|
id: "get-build-options"
|
||||||
|
uses: "./.gitea/actions/get-build-options"
|
||||||
|
- name: "Get `backend` version"
|
||||||
|
id: "get-backend-version"
|
||||||
|
uses: "./.gitea/actions/get-service-version"
|
||||||
|
with:
|
||||||
|
service: "backend"
|
||||||
|
- name: "Setup k8s"
|
||||||
|
uses: "./.gitea/actions/setup-k8s"
|
||||||
|
with:
|
||||||
|
arch: "${{ steps.get-build-options.outputs.build-arch }}"
|
||||||
|
- name: "Import Secrets"
|
||||||
|
id: "import-secrets"
|
||||||
|
uses: "hashicorp/vault-action@v2"
|
||||||
|
with:
|
||||||
|
url: "https://vault.bthlabs.pl/"
|
||||||
|
method: "approle"
|
||||||
|
roleId: "${{ secrets.VAULT_ROLE_ID }}"
|
||||||
|
secretId: "${{ secrets.VAULT_SECRET_ID }}"
|
||||||
|
secrets: |
|
||||||
|
gitea/data/k8s.bthlab config | KUBECONFIG_PAYLOAD
|
||||||
|
- name: "Set up kubeconfig"
|
||||||
|
env:
|
||||||
|
KUBECONFIG_PAYLOAD: "${{ steps.import-secrets.outputs.KUBECONFIG_PAYLOAD }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
echo ${KUBECONFIG_PAYLOAD} | base64 -d >"/opt/k8s/etc/kubeconfig"
|
||||||
|
export KUBECONFIG="/opt/k8s/etc/kubeconfig"
|
||||||
|
|
||||||
|
/opt/k8s/bin/kubectl config use-context ${KUBERNETES_CLUSTER}
|
||||||
|
/opt/k8s/bin/kubectl get node
|
||||||
|
- name: "Run `backend` Django migrations"
|
||||||
|
env:
|
||||||
|
BACKEND_TAG: "deployment-${{ steps.get-backend-version.outputs.version }}-${{ steps.get-backend-version.outputs.build-number }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
(
|
||||||
|
cd deployment/hotpocket_bthlab ;
|
||||||
|
export KUBECONFIG="/opt/k8s/etc/kubeconfig" ;
|
||||||
|
/opt/k8s/bin/kubectl config use-context ${KUBERNETES_CLUSTER} ;
|
||||||
|
/opt/k8s/bin/kubectl -n ${KUBERNETES_NAMESPACE} apply -f resources/backend/config-map-local-deps.yaml ;
|
||||||
|
/opt/k8s/bin/kubectl -n ${KUBERNETES_NAMESPACE} set image cronjobs/backend-job-migrations migrations=nexus.bthlab.bthlabs.net:8002/hotpocket/backend:${BACKEND_TAG} ;
|
||||||
|
/opt/k8s/bin/kubectl -n ${KUBERNETES_NAMESPACE} delete jobs --ignore-not-found=true backend-job-migrations ;
|
||||||
|
/opt/k8s/bin/kubectl -n ${KUBERNETES_NAMESPACE} create job backend-job-migrations --from=cronjob/backend-job-migrations ;
|
||||||
|
/opt/k8s/bin/kubectl -n ${KUBERNETES_NAMESPACE} wait --for=condition=complete --timeout=300s job/backend-job-migrations
|
||||||
|
)
|
||||||
|
- name: "Deploy"
|
||||||
|
env:
|
||||||
|
BACKEND_TAG: "deployment-${{ steps.get-backend-version.outputs.version }}-${{ steps.get-backend-version.outputs.build-number }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
(
|
||||||
|
cd deployment/hotpocket_bthlab ;
|
||||||
|
export KUBECONFIG="/opt/k8s/etc/kubeconfig" ;
|
||||||
|
/opt/k8s/bin/kubectl config use-context ${KUBERNETES_CLUSTER} ;
|
||||||
|
/opt/k8s/bin/kustomize edit set image hotpocket-backend=nexus.bthlab.bthlabs.net:8002/hotpocket/backend:${BACKEND_TAG} ;
|
||||||
|
/opt/k8s/bin/kustomize build . | /opt/k8s/bin/kubectl apply -f -
|
||||||
|
)
|
||||||
76
.gitea/workflows/production.yaml
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
name: "Production deployment"
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: ["published"]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-for-production:
|
||||||
|
name: "Build"
|
||||||
|
uses: "./.gitea/workflows/build-deployment-images.yaml"
|
||||||
|
with:
|
||||||
|
target: "deployment"
|
||||||
|
platform: "linux/amd64"
|
||||||
|
secrets:
|
||||||
|
VAULT_ROLE_ID: "${{ secrets.VAULT_ROLE_ID }}"
|
||||||
|
VAULT_SECRET_ID: "${{ secrets.VAULT_SECRET_ID }}"
|
||||||
|
|
||||||
|
deploy-to-production:
|
||||||
|
name: "Deploy"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
needs:
|
||||||
|
- "build-for-production"
|
||||||
|
steps:
|
||||||
|
- name: "Checkout the code"
|
||||||
|
uses: "actions/checkout@v2"
|
||||||
|
- name: "Get build options"
|
||||||
|
id: "get-build-options"
|
||||||
|
uses: "./.gitea/actions/get-build-options"
|
||||||
|
- name: "Get `backend` version"
|
||||||
|
id: "get-backend-version"
|
||||||
|
uses: "./.gitea/actions/get-service-version"
|
||||||
|
with:
|
||||||
|
service: "backend"
|
||||||
|
- name: "Import Secrets"
|
||||||
|
id: "import-secrets"
|
||||||
|
uses: "hashicorp/vault-action@v2"
|
||||||
|
with:
|
||||||
|
url: "https://vault.bthlabs.pl/"
|
||||||
|
method: "approle"
|
||||||
|
roleId: "${{ secrets.VAULT_ROLE_ID }}"
|
||||||
|
secretId: "${{ secrets.VAULT_SECRET_ID }}"
|
||||||
|
secrets: |
|
||||||
|
gitea/data/hotpocket.app ansible_vault_payload | ANSIBLE_VAULT_PAYLOAD ;
|
||||||
|
gitea/data/hotpocket.app ansible_vault_password | ANSIBLE_VAULT_PASSWORD ;
|
||||||
|
gitea/data/hotpocket.app ansible_inventory_payload | ANSIBLE_INVENTORY_PAYLOAD ;
|
||||||
|
gitea/data/hotpocket.app ssh_key_payload | SSH_KEY_PAYLOAD
|
||||||
|
- name: "Setup Ansible"
|
||||||
|
uses: "./.gitea/actions/setup-ansible"
|
||||||
|
- name: "Prepare Ansible secrets"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
mkdir deployment/hotpocket_app/.ci
|
||||||
|
echo "${ANSIBLE_VAULT_PAYLOAD}" | base64 -d >"deployment/hotpocket_app/env_vars/production/vault.yaml"
|
||||||
|
echo "${ANSIBLE_VAULT_PASSWORD}" >"deployment/hotpocket_app/.ci/vault_password"
|
||||||
|
echo "${ANSIBLE_INVENTORY_PAYLOAD}" | base64 -d >"deployment/hotpocket_app/inventory_ci.yaml"
|
||||||
|
echo "${SSH_KEY_PAYLOAD}" | base64 -d >"deployment/hotpocket_app/.ci/ssh_key"
|
||||||
|
chmod 600 deployment/hotpocket_app/.ci/ssh_key
|
||||||
|
- name: "Engage!"
|
||||||
|
env:
|
||||||
|
VERSION: "${{ steps.get-backend-version.outputs.version }}"
|
||||||
|
BUILD: "${{ steps.get-backend-version.outputs.build-number }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
(
|
||||||
|
cd deployment/hotpocket_app ;
|
||||||
|
ANSIBLE_HOST_KEY_CHECKING="False" /opt/ansible/bin/ansible-playbook \
|
||||||
|
-i inventory_ci.yaml \
|
||||||
|
--vault-id hotpocket@.ci/vault_password \
|
||||||
|
-e @env_vars/production/vars.yaml \
|
||||||
|
-e @env_vars/production/vault.yaml \
|
||||||
|
-e hotpocket_app_image_tag="deployment-${VERSION}-${BUILD}" \
|
||||||
|
--limit "*.production.hotpocket.app" \
|
||||||
|
deploy.yaml
|
||||||
|
)
|
||||||
76
.gitea/workflows/staging.yaml
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
name: "Staging deployment"
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: ["published"]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-for-staging:
|
||||||
|
name: "Build"
|
||||||
|
uses: "./.gitea/workflows/build-deployment-images.yaml"
|
||||||
|
with:
|
||||||
|
target: "aio"
|
||||||
|
platform: "linux/amd64"
|
||||||
|
secrets:
|
||||||
|
VAULT_ROLE_ID: "${{ secrets.VAULT_ROLE_ID }}"
|
||||||
|
VAULT_SECRET_ID: "${{ secrets.VAULT_SECRET_ID }}"
|
||||||
|
|
||||||
|
deploy-to-staging:
|
||||||
|
name: "Deploy"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
needs:
|
||||||
|
- "build-for-staging"
|
||||||
|
steps:
|
||||||
|
- name: "Checkout the code"
|
||||||
|
uses: "actions/checkout@v2"
|
||||||
|
- name: "Get build options"
|
||||||
|
id: "get-build-options"
|
||||||
|
uses: "./.gitea/actions/get-build-options"
|
||||||
|
- name: "Get `backend` version"
|
||||||
|
id: "get-backend-version"
|
||||||
|
uses: "./.gitea/actions/get-service-version"
|
||||||
|
with:
|
||||||
|
service: "backend"
|
||||||
|
- name: "Import Secrets"
|
||||||
|
id: "import-secrets"
|
||||||
|
uses: "hashicorp/vault-action@v2"
|
||||||
|
with:
|
||||||
|
url: "https://vault.bthlabs.pl/"
|
||||||
|
method: "approle"
|
||||||
|
roleId: "${{ secrets.VAULT_ROLE_ID }}"
|
||||||
|
secretId: "${{ secrets.VAULT_SECRET_ID }}"
|
||||||
|
secrets: |
|
||||||
|
gitea/data/staging.hotpocket.app ansible_vault_payload | ANSIBLE_VAULT_PAYLOAD ;
|
||||||
|
gitea/data/staging.hotpocket.app ansible_vault_password | ANSIBLE_VAULT_PASSWORD ;
|
||||||
|
gitea/data/staging.hotpocket.app ansible_inventory_payload | ANSIBLE_INVENTORY_PAYLOAD ;
|
||||||
|
gitea/data/staging.hotpocket.app ssh_key_payload | SSH_KEY_PAYLOAD
|
||||||
|
- name: "Setup Ansible"
|
||||||
|
uses: "./.gitea/actions/setup-ansible"
|
||||||
|
- name: "Prepare Ansible secrets"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
mkdir deployment/hotpocket_app/.ci
|
||||||
|
echo "${ANSIBLE_VAULT_PAYLOAD}" | base64 -d >"deployment/hotpocket_app/env_vars/staging/vault.yaml"
|
||||||
|
echo "${ANSIBLE_VAULT_PASSWORD}" >"deployment/hotpocket_app/.ci/vault_password"
|
||||||
|
echo "${ANSIBLE_INVENTORY_PAYLOAD}" | base64 -d >"deployment/hotpocket_app/inventory_ci.yaml"
|
||||||
|
echo "${SSH_KEY_PAYLOAD}" | base64 -d >"deployment/hotpocket_app/.ci/ssh_key"
|
||||||
|
chmod 600 deployment/hotpocket_app/.ci/ssh_key
|
||||||
|
- name: "Engage!"
|
||||||
|
env:
|
||||||
|
VERSION: "${{ steps.get-backend-version.outputs.version }}"
|
||||||
|
BUILD: "${{ steps.get-backend-version.outputs.build-number }}"
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
(
|
||||||
|
cd deployment/hotpocket_app ;
|
||||||
|
ANSIBLE_HOST_KEY_CHECKING="False" /opt/ansible/bin/ansible-playbook \
|
||||||
|
-i inventory_ci.yaml \
|
||||||
|
--vault-id hotpocket@.ci/vault_password \
|
||||||
|
-e @env_vars/staging/vars.yaml \
|
||||||
|
-e @env_vars/staging/vault.yaml \
|
||||||
|
-e hotpocket_app_image_tag="aio-${VERSION}-${BUILD}" \
|
||||||
|
--limit "*.staging.hotpocket.app" \
|
||||||
|
deploy.yaml
|
||||||
|
)
|
||||||
3
.gitignore
vendored
@@ -1,2 +1,5 @@
|
|||||||
|
.ci/
|
||||||
.envrc*
|
.envrc*
|
||||||
.ipythonhome/
|
.ipythonhome/
|
||||||
|
services/vendor/
|
||||||
|
/docker-compose-ci-*.yaml
|
||||||
|
|||||||
@@ -86,3 +86,9 @@ Licensed under terms of the MIT License
|
|||||||
Pepper Hot Solid icon
|
Pepper Hot Solid icon
|
||||||
Copyright (c) Icons8
|
Copyright (c) Icons8
|
||||||
Licensed under terms of the MIT License
|
Licensed under terms of the MIT License
|
||||||
|
|
||||||
|
Spinner Loader CSS from https://css-loaders.com/
|
||||||
|
|
||||||
|
cosmo, sandstone, sketchy and solar Bootswatch Themes
|
||||||
|
Copyright 2012-2025 Thomas Park
|
||||||
|
Licensed under terms of the MIT License
|
||||||
|
|||||||
41
README.md
@@ -1,13 +1,30 @@
|
|||||||
# HotPocket by BTHLabs
|
# HotPocket by BTHLabs
|
||||||
|
|
||||||
This repository contains the _HotPocket_ project.
|
Minimal self-hosted bookmarking app :).
|
||||||
|
|
||||||
|
## The what, the why and the ugly
|
||||||
|
|
||||||
|
HotPocket is a minimal self-hosted bookmarking app. It combines a Web
|
||||||
|
application, companion apps, browser extensions to give you a way to quickly
|
||||||
|
save links for later.
|
||||||
|
|
||||||
|
HotPocket came to be to fill in the blank left by Pocket, after Mozilla shut it
|
||||||
|
down. I looked at the existing alternatives and found them either too
|
||||||
|
feature-rich, too involved to self-host or otherwise not to my liking. So I
|
||||||
|
decided to sit down and build something for myself.
|
||||||
|
|
||||||
|
With the what and why out of the way, let's talk about the ugly... At its core
|
||||||
|
HotPocket is a personal project. I built it by myself and for myself. It may
|
||||||
|
or may not fit your needs. If it does, happy saving!
|
||||||
|
|
||||||
|
If you're feeling up for an adventure, continue reading below :).
|
||||||
|
|
||||||
## Development setup
|
## Development setup
|
||||||
|
|
||||||
### Requirements:
|
### Requirements:
|
||||||
|
|
||||||
* Python 3.12,
|
* Python 3.13,
|
||||||
* Poetry 1.8.3,
|
* Poetry 2.2.1,
|
||||||
* `git-crypt`,
|
* `git-crypt`,
|
||||||
* Docker with Docker Compose and Buildx.
|
* Docker with Docker Compose and Buildx.
|
||||||
|
|
||||||
@@ -66,7 +83,7 @@ $ docker run --rm -it \
|
|||||||
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME=hotpocket \
|
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME=hotpocket \
|
||||||
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD=hotpocketm4st3r \
|
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD=hotpocketm4st3r \
|
||||||
-p 8000:8000 \
|
-p 8000:8000 \
|
||||||
docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v25.10.4-01
|
hotpocket/backend:aio-v25.11.26-01
|
||||||
```
|
```
|
||||||
|
|
||||||
The command above will set up and start the application. The SQLite file will
|
The command above will set up and start the application. The SQLite file will
|
||||||
@@ -76,8 +93,7 @@ credentials. The Web app will be reachable at `http://127.0.0.1:8000/`.
|
|||||||
The admin will be reachable at `http://127.0.0.1:8000/admin/`.
|
The admin will be reachable at `http://127.0.0.1:8000/admin/`.
|
||||||
|
|
||||||
The `DJANGO_SETTINGS_MODULE` environment variable defaults to
|
The `DJANGO_SETTINGS_MODULE` environment variable defaults to
|
||||||
`hotpocket_backend.settings.deployment.webapp`. This should be set to
|
`hotpocket_backend.settings.deployment.aio`.
|
||||||
`hotpocket_backend.settings.deployment.admin` in the Admin container.
|
|
||||||
|
|
||||||
**NOTE:** The command above specifies wildly insecure `SECRET_KEY` which is
|
**NOTE:** The command above specifies wildly insecure `SECRET_KEY` which is
|
||||||
used among other things to secure the session cookie. Please *please*
|
used among other things to secure the session cookie. Please *please*
|
||||||
@@ -94,7 +110,8 @@ backend etc. The final deployment will require services for at least the Web
|
|||||||
app, the Celery worker and Celery Beat. Admin is optional.
|
app, the Celery worker and Celery Beat. Admin is optional.
|
||||||
|
|
||||||
The `DJANGO_SETTINGS_MODULE` environment variable defaults to
|
The `DJANGO_SETTINGS_MODULE` environment variable defaults to
|
||||||
`hotpocket_backend.settings.deployment.aio`.
|
`hotpocket_backend.settings.deployment.webapp`. This should be set to
|
||||||
|
`hotpocket_backend.settings.deployment.admin` in the Admin container.
|
||||||
|
|
||||||
The `deployment/fullstack/docker-compose.yaml` file can be used as a
|
The `deployment/fullstack/docker-compose.yaml` file can be used as a
|
||||||
starting point for full-stack deployments.
|
starting point for full-stack deployments.
|
||||||
@@ -128,6 +145,7 @@ that can be used to configure the services.
|
|||||||
| `HOTPOCKET_BACKEND_RUN_MIGRATIONS` | `false` or `true` | Set to `true` to run database muigrations when the container starts. |
|
| `HOTPOCKET_BACKEND_RUN_MIGRATIONS` | `false` or `true` | Set to `true` to run database muigrations when the container starts. |
|
||||||
| `HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME` | N/A | Username for the initial account. |
|
| `HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME` | N/A | Username for the initial account. |
|
||||||
| `HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD` | N/A | Password for the initial account. |
|
| `HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD` | N/A | Password for the initial account. |
|
||||||
|
| `HOTPOCKET_BACKEND_OPERATOR_EMAIL` | N/A | Instance operator's e-mail. Used to display extra language on login page. |
|
||||||
|
|
||||||
**Env and App settings**
|
**Env and App settings**
|
||||||
|
|
||||||
@@ -158,6 +176,15 @@ method's name in the UI and defaults to `OIDC`.
|
|||||||
|
|
||||||
**NOTE:** Currently, only Keycloak has been tested with this login method.
|
**NOTE:** Currently, only Keycloak has been tested with this login method.
|
||||||
|
|
||||||
|
### Volumes
|
||||||
|
|
||||||
|
Both images declare `/srv/run` to be a volume. It's intended to keep the
|
||||||
|
service's runtime data, including but not limited to PID files, UNIX sockets
|
||||||
|
etc. It's recommended to persist this volume.
|
||||||
|
|
||||||
|
Additionally, the `deployment` image declares `/srv/uploads` to be a volume.
|
||||||
|
It's recommeded to persist this volume.
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
_HotPocket_ is developed by [BTHLabs](https://www.bthlabs.pl/).
|
_HotPocket_ is developed by [BTHLabs](https://www.bthlabs.pl/).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v25.10.4-01"
|
image: "bthlabs/hotpocket:aio-v25.11.26-01"
|
||||||
environment:
|
environment:
|
||||||
HOTPOCKET_BACKEND_SECRET_KEY: "thisisntright"
|
HOTPOCKET_BACKEND_SECRET_KEY: "thisisntright"
|
||||||
HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME: "hotpocket"
|
HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME: "hotpocket"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ x-backend-environment: &x-backend-environment
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
webapp:
|
webapp:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.10.4-01"
|
image: "bthlabs/hotpocket:deployment-v25.11.26-01"
|
||||||
environment:
|
environment:
|
||||||
<<: *x-backend-environment
|
<<: *x-backend-environment
|
||||||
HOTPOCKET_BACKEND_ALLOWED_HOSTS: "app.staging.hotpocket.bthlab.bthlabs.net"
|
HOTPOCKET_BACKEND_ALLOWED_HOSTS: "app.staging.hotpocket.bthlab.bthlabs.net"
|
||||||
@@ -21,7 +21,7 @@ services:
|
|||||||
restart: "unless-stopped"
|
restart: "unless-stopped"
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.10.4-01"
|
image: "bthlabs/hotpocket:deployment-v25.11.26-01"
|
||||||
environment:
|
environment:
|
||||||
<<: *x-backend-environment
|
<<: *x-backend-environment
|
||||||
HOTPOCKET_BACKEND_APP: "admin"
|
HOTPOCKET_BACKEND_APP: "admin"
|
||||||
@@ -35,7 +35,7 @@ services:
|
|||||||
restart: "unless-stopped"
|
restart: "unless-stopped"
|
||||||
|
|
||||||
celery-worker:
|
celery-worker:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.10.4-01"
|
image: "bthlabs/hotpocket:deployment-v25.11.26-01"
|
||||||
command:
|
command:
|
||||||
- "/srv/venv/bin/celery"
|
- "/srv/venv/bin/celery"
|
||||||
- "-A"
|
- "-A"
|
||||||
@@ -57,7 +57,7 @@ services:
|
|||||||
restart: "unless-stopped"
|
restart: "unless-stopped"
|
||||||
|
|
||||||
celery-beat:
|
celery-beat:
|
||||||
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v25.10.4-01"
|
image: "bthlabs/hotpocket:deployment-v25.11.26-01"
|
||||||
command:
|
command:
|
||||||
- "/srv/venv/bin/celery"
|
- "/srv/venv/bin/celery"
|
||||||
- "-A"
|
- "-A"
|
||||||
|
|||||||
3
deployment/hotpocket_app/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.ci/
|
||||||
|
inventory_ci.yaml
|
||||||
|
vault.yaml
|
||||||
5
deployment/hotpocket_app/deploy.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
- name: "Deploy HotPocket"
|
||||||
|
hosts: "hotpocket_app"
|
||||||
|
roles:
|
||||||
|
- role: "hotpocket_app"
|
||||||
|
tags: ["hotpocket-app"]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
export PIP_INDEX_URL="https://nexus.bthlabs.pl/repository/pypi/simple/"
|
||||||
|
/srv/venv/bin/pip install -r /srv/lib/backend/requirements.txt
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
(
|
||||||
|
cd /srv/app;
|
||||||
|
./manage.py collectstatic --no-input
|
||||||
|
)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
hotpocket-bthlabs>=25.10.28
|
||||||
60
deployment/hotpocket_app/env_vars/production/vars.yaml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
hotpocket_app:
|
||||||
|
deployment_directory: "/srv/hotpocket"
|
||||||
|
owner: "hotpocket"
|
||||||
|
group: "hotpocket"
|
||||||
|
mode: "fullstack"
|
||||||
|
loki:
|
||||||
|
url: "http://monitoring.vm.snakeweb.net.bthlabs.net:3100/loki/api/v1/push"
|
||||||
|
node: "home.vm.snakeweb.net"
|
||||||
|
docker:
|
||||||
|
extra_hosts:
|
||||||
|
- "home.vm:10.0.1.2"
|
||||||
|
backend:
|
||||||
|
image_tag: "{{ hotpocket_app_image_tag|default('deployment-v25.10.21-01') }}"
|
||||||
|
database:
|
||||||
|
name: "thisissecret"
|
||||||
|
user: "thisissecret"
|
||||||
|
host: "thisissecret"
|
||||||
|
rabbitmq:
|
||||||
|
vhost: "thisissecret"
|
||||||
|
user: "thisissecret"
|
||||||
|
host: "thisissecret"
|
||||||
|
model_auth_is_disabled: true
|
||||||
|
env: "production"
|
||||||
|
extra_env:
|
||||||
|
- "HOTPOCKET_BACKEND_SECRETS_PACKAGE=hotpocket_bthlabs.secrets"
|
||||||
|
- "VAULT_URL={{ hotpocket_app_secrets.backend.vault.url }}"
|
||||||
|
- "VAULT_ROLE_ID={{ hotpocket_app_secrets.backend.vault.role_id }}"
|
||||||
|
- "VAULT_SECRET_ID={{ hotpocket_app_secrets.backend.vault.secret_id }}"
|
||||||
|
oidc:
|
||||||
|
enabled: true
|
||||||
|
endpoint: "thisissecret"
|
||||||
|
display_name: "thisissecret"
|
||||||
|
webapp:
|
||||||
|
settings_module: "hotpocket_bthlabs.settings.webapp"
|
||||||
|
loki:
|
||||||
|
external_labels: "job=hotpocket,service=backend-webapp,environment=production"
|
||||||
|
allowed_hosts:
|
||||||
|
- "my.hotpocket.app"
|
||||||
|
admin:
|
||||||
|
settings_module: "hotpocket_bthlabs.settings.admin"
|
||||||
|
loki:
|
||||||
|
external_labels: "job=hotpocket,service=backend-admin,environment=production"
|
||||||
|
allowed_hosts:
|
||||||
|
- "admin.hotpocket.app"
|
||||||
|
celery_worker:
|
||||||
|
concurrency: 2
|
||||||
|
loki:
|
||||||
|
external_labels: "job=hotpocket,service=backend-celery-worker,environment=production"
|
||||||
|
celery_beat:
|
||||||
|
loki:
|
||||||
|
external_labels: "job=hotpocket,service=backend-celery-beat,environment=production"
|
||||||
|
customization:
|
||||||
|
- src: "{{ inventory_dir }}/env_vars/production/etc/backend/entrypoint.d/01-install-customized-deps.sh"
|
||||||
|
dest: "etc/backend/entrypoint.d/01-install-customized-deps.sh"
|
||||||
|
mode: "755"
|
||||||
|
- src: "{{ inventory_dir }}/env_vars/production/etc/backend/entrypoint.d/99-collectstatic.sh"
|
||||||
|
dest: "etc/backend/entrypoint.d/99-collectstatic.sh"
|
||||||
|
mode: "755"
|
||||||
|
- src: "{{ inventory_dir }}/env_vars/production/lib/backend/requirements.txt"
|
||||||
|
dest: "lib/backend/requirements.txt"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
export PIP_INDEX_URL="https://nexus.bthlabs.pl/repository/pypi/simple/"
|
||||||
|
/srv/venv/bin/pip install -r /srv/lib/backend/requirements.txt
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
(
|
||||||
|
cd /srv/app;
|
||||||
|
./manage.py collectstatic --no-input
|
||||||
|
)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
hotpocket-bthlabs>=25.10.28
|
||||||
37
deployment/hotpocket_app/env_vars/staging/vars.yaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
hotpocket_app:
|
||||||
|
deployment_directory: "/srv/hotpocket_staging"
|
||||||
|
owner: "hotpocket_staging"
|
||||||
|
group: "hotpocket_staging"
|
||||||
|
mode: "aio"
|
||||||
|
loki:
|
||||||
|
url: "http://monitoring.vm.snakeweb.net.bthlabs.net:3100/loki/api/v1/push"
|
||||||
|
node: "home.vm.snakeweb.net"
|
||||||
|
docker:
|
||||||
|
extra_hosts:
|
||||||
|
- "home.vm:10.0.1.2"
|
||||||
|
backend:
|
||||||
|
image_tag: "{{ hotpocket_app_image_tag|default('aio-v25.10.29-rc1-01') }}"
|
||||||
|
model_auth_is_disabled: false
|
||||||
|
env: "staging"
|
||||||
|
extra_env:
|
||||||
|
- "HOTPOCKET_BACKEND_SECRETS_PACKAGE=hotpocket_bthlabs.secrets"
|
||||||
|
- "VAULT_URL={{ hotpocket_app_secrets.backend.vault.url }}"
|
||||||
|
- "VAULT_ROLE_ID={{ hotpocket_app_secrets.backend.vault.role_id }}"
|
||||||
|
- "VAULT_SECRET_ID={{ hotpocket_app_secrets.backend.vault.secret_id }}"
|
||||||
|
oidc:
|
||||||
|
enabled: false
|
||||||
|
webapp:
|
||||||
|
settings_module: "hotpocket_bthlabs.settings.webapp"
|
||||||
|
loki:
|
||||||
|
external_labels: "job=hotpocket,service=backend-webapp,environment=staging"
|
||||||
|
allowed_hosts:
|
||||||
|
- "staging.hotpocket.app"
|
||||||
|
customization:
|
||||||
|
- src: "{{ inventory_dir }}/env_vars/staging/etc/backend/entrypoint.d/01-install-customized-deps.sh"
|
||||||
|
dest: "etc/backend/entrypoint.d/01-install-customized-deps.sh"
|
||||||
|
mode: "755"
|
||||||
|
- src: "{{ inventory_dir }}/env_vars/staging/etc/backend/entrypoint.d/99-collectstatic.sh"
|
||||||
|
dest: "etc/backend/entrypoint.d/99-collectstatic.sh"
|
||||||
|
mode: "755"
|
||||||
|
- src: "{{ inventory_dir }}/env_vars/staging/lib/backend/requirements.txt"
|
||||||
|
dest: "lib/backend/requirements.txt"
|
||||||
10
deployment/hotpocket_app/inventory.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
hotpocket_app:
|
||||||
|
hosts:
|
||||||
|
web1.staging.hotpocket.app:
|
||||||
|
ansible_host: vm-125.homelab01.bthlab
|
||||||
|
ansible_port: 22
|
||||||
|
ansible_user: hotpocket_staging
|
||||||
|
web1.production.hotpocket.app:
|
||||||
|
ansible_host: vm-125.homelab01.bthlab
|
||||||
|
ansible_port: 22
|
||||||
|
ansible_user: hotpocket
|
||||||
73
deployment/hotpocket_app/roles/hotpocket_app/tasks/main.yaml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
- name: "Create workspace directories"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ hotpocket_app.deployment_directory }}/{{ item }}"
|
||||||
|
state: "directory"
|
||||||
|
loop:
|
||||||
|
- "etc"
|
||||||
|
- "etc/backend"
|
||||||
|
- "etc/backend/entrypoint.d"
|
||||||
|
- "lib"
|
||||||
|
- "lib/backend"
|
||||||
|
- "log"
|
||||||
|
- "run"
|
||||||
|
- "run/backend-admin"
|
||||||
|
- "run/backend-celery-beat"
|
||||||
|
- "run/backend-celery-worker"
|
||||||
|
- "run/backend-webapp"
|
||||||
|
- "run/uploads"
|
||||||
|
- name: "Install docker-compose.yml"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "templates/{{ hotpocket_app.mode }}/docker-compose.yaml.jinja2"
|
||||||
|
dest: "{{ hotpocket_app.deployment_directory }}/docker-compose.yaml"
|
||||||
|
owner: "{{ hotpocket_app.owner }}"
|
||||||
|
group: "{{ hotpocket_app.group }}"
|
||||||
|
- name: "Install env files"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "templates/{{ hotpocket_app.mode }}/{{ item }}.jinja2"
|
||||||
|
dest: "{{ hotpocket_app.deployment_directory }}/etc/{{ item }}"
|
||||||
|
owner: "{{ hotpocket_app.owner }}"
|
||||||
|
group: "{{ hotpocket_app.group }}"
|
||||||
|
loop: "{{ hotpocket_app_role.env_files[hotpocket_app.mode] }}"
|
||||||
|
- name: "Upload customization files"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ item.src }}"
|
||||||
|
dest: "{{ hotpocket_app.deployment_directory }}/{{ item.dest }}"
|
||||||
|
owner: "{{ hotpocket_app.owner }}"
|
||||||
|
group: "{{ hotpocket_app.group }}"
|
||||||
|
mode: "{{ item.mode|default('644') }}"
|
||||||
|
loop: "{{ hotpocket_app.customization }}"
|
||||||
|
when: "hotpocket_app.customization is defined"
|
||||||
|
- name: "Install hotpocket_app.service unit"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "templates/{{ hotpocket_app_role.services[hotpocket_app.mode].src }}.jinja2"
|
||||||
|
dest: "{{ hotpocket_app.deployment_directory }}/etc/{{ hotpocket_app_role.services[hotpocket_app.mode].dest }}"
|
||||||
|
owner: "{{ hotpocket_app.owner }}"
|
||||||
|
group: "{{ hotpocket_app.group }}"
|
||||||
|
- name: "Stop the stack"
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- "docker"
|
||||||
|
- "compose"
|
||||||
|
- "down"
|
||||||
|
chdir: "{{ hotpocket_app.deployment_directory }}"
|
||||||
|
- name: "Run backend migrations"
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- "docker"
|
||||||
|
- "compose"
|
||||||
|
- "run"
|
||||||
|
- "--rm"
|
||||||
|
- "backend-webapp"
|
||||||
|
- "./manage.py"
|
||||||
|
- "migrate"
|
||||||
|
chdir: "{{ hotpocket_app.deployment_directory }}"
|
||||||
|
when: "hotpocket_app.mode == 'fullstack' and is_manual_run is not defined"
|
||||||
|
- name: "Start the stack"
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- "docker"
|
||||||
|
- "compose"
|
||||||
|
- "up"
|
||||||
|
- "-d"
|
||||||
|
chdir: "{{ hotpocket_app.deployment_directory }}"
|
||||||
|
when: "is_manual_run is not defined"
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
DJANGO_SETTINGS_MODULE="{{ hotpocket_app.backend.webapp.settings_module|default('hotpocket_backend.settings.aio')}}"
|
||||||
|
HOTPOCKET_BACKEND_ENV="{{ hotpocket_app.backend.env|default('aio') }}"
|
||||||
|
HOTPOCKET_BACKEND_MODEL_AUTH_IS_DISABLED="{% if hotpocket_app.backend.model_auth_is_disabled %}true{% else %}false{% endif %}"
|
||||||
|
|
||||||
|
{% if hotpocket_app.backend.oidc.enabled %}HOTPOCKET_BACKEND_OIDC_PAYLOAD='{"endpoint":"{{ hotpocket_app.backend.oidc.endpoint }}","key":"{{ hotpocket_app_secrets.backend.oidc.key }}","secret":"{{ hotpocket_app_secrets.backend.oidc.secret }}","display_name":"{{ hotpocket_app.backend.oidc.display_name }}"}'{% else %}#noop{% endif %}
|
||||||
|
|
||||||
|
{% for extra_env in hotpocket_app.backend.extra_env|default([]) %}
|
||||||
|
{{ extra_env }}
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
HOTPOCKET_BACKEND_SECRET_KEY: "{{ hotpocket_app_secrets.backend.webapp.secret_key }}"
|
||||||
|
HOTPOCKET_BACKEND_ALLOWED_HOSTS="{{ hotpocket_app.backend.webapp.allowed_hosts|join(',') }}"
|
||||||
|
HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME: "{{ hotpocket_app_secrets.backend.webapp.initial_account.username }}"
|
||||||
|
HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD: "{{ hotpocket_app_secrets.backend.webapp.initial_account.password }}"
|
||||||
|
{% for extra_env in hotpocket_app.backend.webapp.extra_env|default([]) %}
|
||||||
|
{{ extra_env }}
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
services:
|
||||||
|
backend-webapp:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:{{ hotpocket_app.backend.image_tag }}"
|
||||||
|
command:
|
||||||
|
- "/srv/venv/bin/gunicorn"
|
||||||
|
- "-c"
|
||||||
|
- "/srv/lib/gunicorn.conf.py"
|
||||||
|
- "-b"
|
||||||
|
- "unix:///srv/run/gunicorn.sock"
|
||||||
|
- "hotpocket_backend.wsgi:application"
|
||||||
|
logging:
|
||||||
|
driver: "loki"
|
||||||
|
options:
|
||||||
|
loki-url: "{{ hotpocket_app.loki.url }}"
|
||||||
|
loki-external-labels: "{{ hotpocket_app.backend.webapp.loki.external_labels }}"
|
||||||
|
labels: "node"
|
||||||
|
labels:
|
||||||
|
node: "{{ hotpocket_app.loki.node }}"
|
||||||
|
env_file:
|
||||||
|
- "etc/backend_base.env"
|
||||||
|
- "etc/backend_webapp.env"
|
||||||
|
extra_hosts: [{% for extra_host in hotpocket_app.docker.extra_hosts|default([]) %}"{{ extra_host }}"{% endfor %}]
|
||||||
|
restart: "unless-stopped"
|
||||||
|
volumes:
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/etc/backend:/srv/etc"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/lib/backend:/srv/lib/backend"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/backend-webapp:/srv/run"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/uploads:/srv/uploads"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
DJANGO_SETTINGS_MODULE="{{ hotpocket_app.backend.admin.settings_module|default('hotpocket_backend.settings.deployment.admin')}}"
|
||||||
|
HOTPOCKET_BACKEND_GUNICORN_WORKERS=2
|
||||||
|
HOTPOCKET_BACKEND_APP="admin"
|
||||||
|
HOTPOCKET_BACKEND_SECRET_KEY="{{ hotpocket_app_secrets.backend.admin.secret_key }}"
|
||||||
|
HOTPOCKET_BACKEND_ALLOWED_HOSTS="{{ hotpocket_app.backend.admin.allowed_hosts|join(',') }}"
|
||||||
|
{% for extra_env in hotpocket_app.backend.admin.extra_env|default([]) %}
|
||||||
|
{{ extra_env }}
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
HOTPOCKET_BACKEND_ENV="{{ hotpocket_app.backend.env|default('deployment') }}"
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_NAME="{{ hotpocket_app.backend.database.name }}"
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_USER="{{ hotpocket_app.backend.database.user }}"
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_PASSWORD="{{ hotpocket_app_secrets.backend.database.password }}"
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_HOST="{{ hotpocket_app.backend.database.host }}"
|
||||||
|
HOTPOCKET_BACKEND_CELERY_BROKER_URL="amqp://{{ hotpocket_app.backend.rabbitmq.user }}:{{ hotpocket_app_secrets.backend.rabbitmq.password }}@{{ hotpocket_app.backend.rabbitmq.host }}/{{ hotpocket_app.backend.rabbitmq.vhost }}"
|
||||||
|
HOTPOCKET_BACKEND_CELERY_RESULT_BACKEND="db+postgresql+psycopg://{{ hotpocket_app.backend.database.user }}:{{ hotpocket_app_secrets.backend.database.password }}@{{ hotpocket_app.backend.database.host }}/{{ hotpocket_app.backend.database.name }}"
|
||||||
|
HOTPOCKET_BACKEND_MODEL_AUTH_IS_DISABLED="{% if hotpocket_app.backend.model_auth_is_disabled %}true{% else %}false{% endif %}"
|
||||||
|
|
||||||
|
{% if hotpocket_app.backend.oidc.enabled %}HOTPOCKET_BACKEND_OIDC_PAYLOAD='{"endpoint":"{{ hotpocket_app.backend.oidc.endpoint }}","key":"{{ hotpocket_app_secrets.backend.oidc.key }}","secret":"{{ hotpocket_app_secrets.backend.oidc.secret }}","display_name":"{{ hotpocket_app.backend.oidc.display_name }}"}'{% else %}#noop{% endif %}
|
||||||
|
|
||||||
|
{% for extra_env in hotpocket_app.backend.extra_env|default([]) %}
|
||||||
|
{{ extra_env }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
DJANGO_SETTINGS_MODULE="{{ hotpocket_app.backend.webapp.settings_module|default('hotpocket_backend.settings.deployment.webapp')}}"
|
||||||
|
HOTPOCKET_BACKEND_APP="webapp"
|
||||||
|
HOTPOCKET_BACKEND_SECRET_KEY="{{ hotpocket_app_secrets.backend.webapp.secret_key }}"
|
||||||
|
HOTPOCKET_BACKEND_ALLOWED_HOSTS="{{ hotpocket_app.backend.webapp.allowed_hosts|join(',') }}"
|
||||||
|
HOTPOCKET_BACKEND_SAVES_SAVE_ADAPTER="hotpocket_backend.apps.saves.adapters.postgres:PostgresSaveAdapter"
|
||||||
|
HOTPOCKET_BACKEND_SAVES_ASSOCIATION_ADAPTER="hotpocket_backend.apps.saves.adapters.postgres:PostgresAssociationAdapter"
|
||||||
|
{% for extra_env in hotpocket_app.backend.webapp.extra_env|default([]) %}
|
||||||
|
{{ extra_env }}
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
services:
|
||||||
|
backend-webapp:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:{{ hotpocket_app.backend.image_tag }}"
|
||||||
|
command:
|
||||||
|
- "/srv/venv/bin/gunicorn"
|
||||||
|
- "-c"
|
||||||
|
- "/srv/lib/gunicorn.conf.py"
|
||||||
|
- "-b"
|
||||||
|
- "unix:///srv/run/gunicorn.sock"
|
||||||
|
- "hotpocket_backend.wsgi:application"
|
||||||
|
logging:
|
||||||
|
driver: "loki"
|
||||||
|
options:
|
||||||
|
loki-url: "{{ hotpocket_app.loki.url }}"
|
||||||
|
loki-external-labels: "{{ hotpocket_app.backend.webapp.loki.external_labels }}"
|
||||||
|
labels: "node"
|
||||||
|
labels:
|
||||||
|
node: "{{ hotpocket_app.loki.node }}"
|
||||||
|
env_file:
|
||||||
|
- "etc/backend_base.env"
|
||||||
|
- "etc/backend_webapp.env"
|
||||||
|
extra_hosts: [{% for extra_host in hotpocket_app.docker.extra_hosts %}"{{ extra_host }}"{% endfor %}]
|
||||||
|
restart: "unless-stopped"
|
||||||
|
volumes:
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/etc/backend:/srv/etc"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/lib/backend:/srv/lib/backend"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/backend-webapp:/srv/run"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/uploads:/srv/uploads"
|
||||||
|
|
||||||
|
backend-admin:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:{{ hotpocket_app.backend.image_tag }}"
|
||||||
|
command:
|
||||||
|
- "/srv/venv/bin/gunicorn"
|
||||||
|
- "-c"
|
||||||
|
- "/srv/lib/gunicorn.conf.py"
|
||||||
|
- "-b"
|
||||||
|
- "unix:///srv/run/gunicorn.sock"
|
||||||
|
- "hotpocket_backend.wsgi:application"
|
||||||
|
logging:
|
||||||
|
driver: "loki"
|
||||||
|
options:
|
||||||
|
loki-url: "{{ hotpocket_app.loki.url }}"
|
||||||
|
loki-external-labels: "{{ hotpocket_app.backend.admin.loki.external_labels }}"
|
||||||
|
labels: "node"
|
||||||
|
labels:
|
||||||
|
node: "{{ hotpocket_app.loki.node }}"
|
||||||
|
env_file:
|
||||||
|
- "etc/backend_base.env"
|
||||||
|
- "etc/backend_admin.env"
|
||||||
|
extra_hosts: [{% for extra_host in hotpocket_app.docker.extra_hosts %}"{{ extra_host }}"{% endfor %}]
|
||||||
|
restart: "unless-stopped"
|
||||||
|
volumes:
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/etc/backend:/srv/etc"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/lib/backend:/srv/lib/backend"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/backend-admin:/srv/run"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/uploads:/srv/uploads"
|
||||||
|
|
||||||
|
backend-celery-worker:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:{{ hotpocket_app.backend.image_tag }}"
|
||||||
|
command:
|
||||||
|
- "/srv/venv/bin/celery"
|
||||||
|
- "-A"
|
||||||
|
- "hotpocket_backend.celery:app"
|
||||||
|
- "worker"
|
||||||
|
- "-l"
|
||||||
|
- "INFO"
|
||||||
|
- "-Q"
|
||||||
|
- "celery,webapp"
|
||||||
|
- "-c"
|
||||||
|
- "{{ hotpocket_app.backend.celery_worker.concurrency }}"
|
||||||
|
logging:
|
||||||
|
driver: "loki"
|
||||||
|
options:
|
||||||
|
loki-url: "{{ hotpocket_app.loki.url }}"
|
||||||
|
loki-external-labels: "{{ hotpocket_app.backend.celery_worker.loki.external_labels }}"
|
||||||
|
labels: "node"
|
||||||
|
labels:
|
||||||
|
node: "{{ hotpocket_app.loki.node }}"
|
||||||
|
env_file:
|
||||||
|
- "etc/backend_base.env"
|
||||||
|
- "etc/backend_webapp.env"
|
||||||
|
extra_hosts: [{% for extra_host in hotpocket_app.docker.extra_hosts %}"{{ extra_host }}"{% endfor %}]
|
||||||
|
restart: "unless-stopped"
|
||||||
|
volumes:
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/etc/backend:/srv/etc"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/lib/backend:/srv/lib/backend"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/backend-celery-worker:/srv/run"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/uploads:/srv/uploads"
|
||||||
|
|
||||||
|
backend-celery-beat:
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:{{ hotpocket_app.backend.image_tag }}"
|
||||||
|
command:
|
||||||
|
- "/srv/venv/bin/celery"
|
||||||
|
- "-A"
|
||||||
|
- "hotpocket_backend.celery:app"
|
||||||
|
- "beat"
|
||||||
|
- "-l"
|
||||||
|
- "INFO"
|
||||||
|
- "-s"
|
||||||
|
- "/srv/run/celery-beat-schedule"
|
||||||
|
logging:
|
||||||
|
driver: "loki"
|
||||||
|
options:
|
||||||
|
loki-url: "{{ hotpocket_app.loki.url }}"
|
||||||
|
loki-external-labels: "{{ hotpocket_app.backend.celery_beat.loki.external_labels }}"
|
||||||
|
labels: "node"
|
||||||
|
labels:
|
||||||
|
node: "{{ hotpocket_app.loki.node }}"
|
||||||
|
env_file:
|
||||||
|
- "etc/backend_base.env"
|
||||||
|
- "etc/backend_webapp.env"
|
||||||
|
extra_hosts: [{% for extra_host in hotpocket_app.docker.extra_hosts %}"{{ extra_host }}"{% endfor %}]
|
||||||
|
restart: "unless-stopped"
|
||||||
|
volumes:
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/etc/backend:/srv/etc"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/lib/backend:/srv/lib/backend"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/backend-celery-beat:/srv/run"
|
||||||
|
- "{{ hotpocket_app.deployment_directory }}/run/uploads:/srv/uploads"
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=hotpocket_backend.webapp
|
||||||
|
Requires=docker.service
|
||||||
|
After=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
WorkingDirectory={{ hotpocket_app.deployment_directory }}
|
||||||
|
ExecStart=/usr/bin/docker compose up -d
|
||||||
|
ExecStop=/usr/bin/docker compose down
|
||||||
|
TimeoutStartSec=0
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
16
deployment/hotpocket_app/roles/hotpocket_app/vars/main.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
hotpocket_app_role:
|
||||||
|
env_files:
|
||||||
|
fullstack:
|
||||||
|
- "backend_admin.env"
|
||||||
|
- "backend_base.env"
|
||||||
|
- "backend_webapp.env"
|
||||||
|
aio:
|
||||||
|
- "backend_base.env"
|
||||||
|
- "backend_webapp.env"
|
||||||
|
services:
|
||||||
|
fullstack:
|
||||||
|
src: "hotpocket_app.service"
|
||||||
|
dest: "hotpocket_app.service"
|
||||||
|
aio:
|
||||||
|
src: "hotpocket_app.service"
|
||||||
|
dest: "staging_hotpocket_app.service"
|
||||||
7
deployment/hotpocket_bthlab/configs/backend/admin
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
DJANGO_SETTINGS_MODULE=hotpocket_bthlabs.settings.admin
|
||||||
|
HOTPOCKET_BACKEND_GUNICORN_WORKERS=2
|
||||||
|
HOTPOCKET_BACKEND_SECRETS_PACKAGE=hotpocket_bthlabs.secrets
|
||||||
|
HOTPOCKET_BACKEND_ENV=development
|
||||||
|
HOTPOCKET_BACKEND_APP=admin
|
||||||
|
HOTPOCKET_BACKEND_SECRET_KEY=thisissecret
|
||||||
|
HOTPOCKET_BACKEND_ALLOWED_HOSTS=admin.hotpocket.bthlab.bthlabs.net
|
||||||
8
deployment/hotpocket_bthlab/configs/backend/base
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
HOTPOCKET_BACKEND_ENV=deployment
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_NAME=hotpocket_development_backend
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_USER=thisissecret
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_PASSWORD=thisissecret
|
||||||
|
HOTPOCKET_BACKEND_DATABASE_HOST=databases.bthlab
|
||||||
|
HOTPOCKET_BACKEND_CELERY_BROKER_URL=thisissecret
|
||||||
|
HOTPOCKET_BACKEND_CELERY_RESULT_BACKEND=thisissecret
|
||||||
|
HOTPOCKET_BACKEND_MODEL_AUTH_IS_DISABLED=false
|
||||||
9
deployment/hotpocket_bthlab/configs/backend/webapp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
DJANGO_SETTINGS_MODULE=hotpocket_bthlabs.settings.webapp
|
||||||
|
HOTPOCKET_BACKEND_GUNICORN_WORKERS=2
|
||||||
|
HOTPOCKET_BACKEND_SECRETS_PACKAGE=hotpocket_bthlabs.secrets
|
||||||
|
HOTPOCKET_BACKEND_ENV=development
|
||||||
|
HOTPOCKET_BACKEND_APP=webapp
|
||||||
|
HOTPOCKET_BACKEND_SECRET_KEY=thisissecret
|
||||||
|
HOTPOCKET_BACKEND_ALLOWED_HOSTS=app.hotpocket.bthlab.bthlabs.net
|
||||||
|
HOTPOCKET_BACKEND_SAVES_SAVE_ADAPTER=hotpocket_backend.apps.saves.adapters.postgres:PostgresSaveAdapter
|
||||||
|
HOTPOCKET_BACKEND_SAVES_ASSOCIATION_ADAPTER=hotpocket_backend.apps.saves.adapters.postgres:PostgresAssociationAdapter
|
||||||
40
deployment/hotpocket_bthlab/kustomization.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- resources/namespace.yaml
|
||||||
|
- resources/volumes.yaml
|
||||||
|
- resources/backend/config-map-local-deps.yaml
|
||||||
|
- resources/backend/job-migrations.yaml
|
||||||
|
- resources/backend/webapp.yaml
|
||||||
|
- resources/backend/webapp-service.yaml
|
||||||
|
- resources/backend/webapp-ingress.yaml
|
||||||
|
- resources/backend/admin.yaml
|
||||||
|
- resources/backend/admin-service.yaml
|
||||||
|
- resources/backend/admin-ingress.yaml
|
||||||
|
- resources/backend/celery-worker.yaml
|
||||||
|
- resources/backend/celery-beat.yaml
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- behavior: create
|
||||||
|
namespace: hotpocket-development
|
||||||
|
envs:
|
||||||
|
- configs/backend/base
|
||||||
|
name: backend-base-config
|
||||||
|
- behavior: create
|
||||||
|
namespace: hotpocket-development
|
||||||
|
envs:
|
||||||
|
- configs/backend/webapp
|
||||||
|
name: backend-webapp-config
|
||||||
|
- behavior: create
|
||||||
|
namespace: hotpocket-development
|
||||||
|
envs:
|
||||||
|
- configs/backend/admin
|
||||||
|
name: backend-admin-config
|
||||||
|
|
||||||
|
patches: []
|
||||||
|
|
||||||
|
images:
|
||||||
|
- name: hotpocket-backend
|
||||||
|
newName: nexus.bthlab.bthlabs.net:8002/hotpocket/backend
|
||||||
|
newTag: deployment-8e09ae51-01
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: backend-admin-ingress
|
||||||
|
namespace: hotpocket-development
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: "web"
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: admin.hotpocket.bthlab.bthlabs.net
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: backend-admin-service
|
||||||
|
port:
|
||||||
|
name: http
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: backend-admin-service
|
||||||
|
namespace: hotpocket-development
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/app: backend-admin
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 8000
|
||||||
|
targetPort: http
|
||||||
99
deployment/hotpocket_bthlab/resources/backend/admin.yaml
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: backend-admin
|
||||||
|
namespace: hotpocket-development
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-admin
|
||||||
|
spec:
|
||||||
|
minReadySeconds: 30
|
||||||
|
progressDeadlineSeconds: 600
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 1
|
||||||
|
maxUnavailable: 1
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/app: backend-admin
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-admin
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: hotpocket-backend:latest
|
||||||
|
args:
|
||||||
|
- "/srv/venv/bin/gunicorn"
|
||||||
|
- "-c"
|
||||||
|
- "/srv/lib/gunicorn.conf.py"
|
||||||
|
- "hotpocket_backend.wsgi:application"
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-base-config
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-admin-config
|
||||||
|
env:
|
||||||
|
- name: VAULT_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: url
|
||||||
|
- name: VAULT_ROLE_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: role_id
|
||||||
|
- name: VAULT_SECRET_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: secret_id
|
||||||
|
ports:
|
||||||
|
- containerPort: 8000
|
||||||
|
name: http
|
||||||
|
protocol: TCP
|
||||||
|
- containerPort: 8001
|
||||||
|
name: healthcheck
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: "/"
|
||||||
|
port: 8001
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: "/"
|
||||||
|
port: 8001
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
periodSeconds: 5
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /dev/shm
|
||||||
|
name: shm
|
||||||
|
- mountPath: /srv/run
|
||||||
|
name: backend-admin-srv-run
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/lib/requirements.txt"
|
||||||
|
subPath: "requirements.txt"
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/etc/entrypoint.d/01-install-extra-deps.sh"
|
||||||
|
subPath: "01-install-extra-deps.sh"
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/etc/entrypoint.d/99-collectstatic.sh"
|
||||||
|
subPath: "99-collectstatic.sh"
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- name: shm
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: backend-admin-srv-run
|
||||||
|
emptyDir: {}
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
configMap:
|
||||||
|
name: "backend-local-deps"
|
||||||
|
defaultMode: 0755
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: backend-celery-beat
|
||||||
|
namespace: hotpocket-development
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-celery-beat
|
||||||
|
spec:
|
||||||
|
minReadySeconds: 30
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/app: backend-celery-beat
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-celery-beat
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: hotpocket-backend:latest
|
||||||
|
args:
|
||||||
|
- "/srv/venv/bin/celery"
|
||||||
|
- "-A"
|
||||||
|
- "hotpocket_backend.celery:app"
|
||||||
|
- "beat"
|
||||||
|
- "-l"
|
||||||
|
- "INFO"
|
||||||
|
- "-s"
|
||||||
|
- "/srv/run/celery-beat-schedule"
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-base-config
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-webapp-config
|
||||||
|
env:
|
||||||
|
- name: VAULT_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: url
|
||||||
|
- name: VAULT_ROLE_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: role_id
|
||||||
|
- name: VAULT_SECRET_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: secret_id
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /dev/shm
|
||||||
|
name: shm
|
||||||
|
- mountPath: /srv/run
|
||||||
|
name: backend-celery-beat-srv-run
|
||||||
|
- mountPath: /srv/uploads
|
||||||
|
name: backend-celery-beat-srv-uploads
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/lib/requirements.txt"
|
||||||
|
subPath: "requirements.txt"
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/etc/entrypoint.d/01-install-extra-deps.sh"
|
||||||
|
subPath: "01-install-extra-deps.sh"
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- name: shm
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: backend-celery-beat-srv-run
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: backend-celery-beat-run
|
||||||
|
- name: backend-celery-beat-srv-uploads
|
||||||
|
emptyDir: {}
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
configMap:
|
||||||
|
name: "backend-local-deps"
|
||||||
|
defaultMode: 0755
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: backend-celery-worker
|
||||||
|
namespace: hotpocket-development
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-celery-worker
|
||||||
|
spec:
|
||||||
|
minReadySeconds: 30
|
||||||
|
progressDeadlineSeconds: 600
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 1
|
||||||
|
maxUnavailable: 1
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/app: backend-celery-worker
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-celery-worker
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: hotpocket-backend:latest
|
||||||
|
args:
|
||||||
|
- "/srv/venv/bin/celery"
|
||||||
|
- "-A"
|
||||||
|
- "hotpocket_backend.celery:app"
|
||||||
|
- "worker"
|
||||||
|
- "-l"
|
||||||
|
- "INFO"
|
||||||
|
- "-Q"
|
||||||
|
- "celery,webapp"
|
||||||
|
- "-c"
|
||||||
|
- "2"
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-base-config
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-webapp-config
|
||||||
|
env:
|
||||||
|
- name: VAULT_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: url
|
||||||
|
- name: VAULT_ROLE_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: role_id
|
||||||
|
- name: VAULT_SECRET_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: secret_id
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /dev/shm
|
||||||
|
name: shm
|
||||||
|
- mountPath: /srv/run
|
||||||
|
name: backend-celery-worker-srv-run
|
||||||
|
- mountPath: /srv/uploads
|
||||||
|
name: backend-celery-worker-srv-uploads
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/lib/requirements.txt"
|
||||||
|
subPath: "requirements.txt"
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/etc/entrypoint.d/01-install-extra-deps.sh"
|
||||||
|
subPath: "01-install-extra-deps.sh"
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- name: shm
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: backend-celery-worker-srv-run
|
||||||
|
emptyDir: {}
|
||||||
|
- name: backend-celery-worker-srv-uploads
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: backend-uploads
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
configMap:
|
||||||
|
name: "backend-local-deps"
|
||||||
|
defaultMode: 0755
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: backend-local-deps
|
||||||
|
namespace: hotpocket-development
|
||||||
|
data:
|
||||||
|
01-install-extra-deps.sh: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
export PIP_INDEX_URL="https://nexus.bthlabs.pl/repository/pypi/simple/"
|
||||||
|
/srv/venv/bin/pip install -r /srv/lib/requirements.txt
|
||||||
|
99-collectstatic.sh: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
(
|
||||||
|
cd /srv/app;
|
||||||
|
./manage.py collectstatic --no-input
|
||||||
|
)
|
||||||
|
requirements.txt: |
|
||||||
|
hotpocket_bthlabs>=25.10.28
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: backend-job-migrations
|
||||||
|
namespace: hotpocket-development
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-job-migrations
|
||||||
|
spec:
|
||||||
|
concurrencyPolicy: "Forbid"
|
||||||
|
successfulJobsHistoryLimit: 1
|
||||||
|
failedJobsHistoryLimit: 1
|
||||||
|
startingDeadlineSeconds: 180
|
||||||
|
schedule: "* * * * *"
|
||||||
|
suspend: true
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
backoffLimit: 1
|
||||||
|
completions: 1
|
||||||
|
parallelism: 1
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: migrations
|
||||||
|
image: hotpocket-backend:latest
|
||||||
|
args:
|
||||||
|
- "./manage.py"
|
||||||
|
- "migrate"
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-base-config
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-webapp-config
|
||||||
|
env:
|
||||||
|
- name: VAULT_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: url
|
||||||
|
- name: VAULT_ROLE_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: role_id
|
||||||
|
- name: VAULT_SECRET_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: secret_id
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /dev/shm
|
||||||
|
name: shm
|
||||||
|
- mountPath: /srv/run
|
||||||
|
name: backend-webapp-srv-run
|
||||||
|
- mountPath: /srv/uploads
|
||||||
|
name: backend-webapp-srv-uploads
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/lib/requirements.txt"
|
||||||
|
subPath: "requirements.txt"
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/etc/entrypoint.d/01-install-extra-deps.sh"
|
||||||
|
subPath: "01-install-extra-deps.sh"
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Never
|
||||||
|
volumes:
|
||||||
|
- name: shm
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: backend-webapp-srv-run
|
||||||
|
emptyDir: {}
|
||||||
|
- name: backend-webapp-srv-uploads
|
||||||
|
emptyDir: {}
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
configMap:
|
||||||
|
name: "backend-local-deps"
|
||||||
|
defaultMode: 0755
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: backend-webapp-ingress
|
||||||
|
namespace: hotpocket-development
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: "web"
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: app.hotpocket.bthlab.bthlabs.net
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: backend-webapp-service
|
||||||
|
port:
|
||||||
|
name: http
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: backend-webapp-service
|
||||||
|
namespace: hotpocket-development
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/app: backend-webapp
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 8000
|
||||||
|
targetPort: http
|
||||||
106
deployment/hotpocket_bthlab/resources/backend/webapp.yaml
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: backend-webapp
|
||||||
|
namespace: hotpocket-development
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-webapp
|
||||||
|
spec:
|
||||||
|
minReadySeconds: 30
|
||||||
|
progressDeadlineSeconds: 600
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 1
|
||||||
|
maxUnavailable: 1
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/app: backend-webapp
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/app: backend-webapp
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: hotpocket-backend:latest
|
||||||
|
args:
|
||||||
|
- "/srv/venv/bin/gunicorn"
|
||||||
|
- "-c"
|
||||||
|
- "/srv/lib/gunicorn.conf.py"
|
||||||
|
- "hotpocket_backend.wsgi:application"
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-base-config
|
||||||
|
- configMapRef:
|
||||||
|
name: backend-webapp-config
|
||||||
|
env:
|
||||||
|
- name: VAULT_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: url
|
||||||
|
- name: VAULT_ROLE_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: role_id
|
||||||
|
- name: VAULT_SECRET_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: backend-vault
|
||||||
|
key: secret_id
|
||||||
|
- name: HOTPOCKET_BACKEND_CREATE_INITIAL_ACCOUNT
|
||||||
|
value: "true"
|
||||||
|
ports:
|
||||||
|
- containerPort: 8000
|
||||||
|
name: http
|
||||||
|
protocol: TCP
|
||||||
|
- containerPort: 8001
|
||||||
|
name: healthcheck
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: "/"
|
||||||
|
port: 8001
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: "/"
|
||||||
|
port: 8001
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
periodSeconds: 5
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /dev/shm
|
||||||
|
name: shm
|
||||||
|
- mountPath: /srv/run
|
||||||
|
name: backend-webapp-srv-run
|
||||||
|
- mountPath: /srv/uploads
|
||||||
|
name: backend-webapp-srv-uploads
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/lib/requirements.txt"
|
||||||
|
subPath: "requirements.txt"
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/etc/entrypoint.d/01-install-extra-deps.sh"
|
||||||
|
subPath: "01-install-extra-deps.sh"
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
mountPath: "/srv/etc/entrypoint.d/99-collectstatic.sh"
|
||||||
|
subPath: "99-collectstatic.sh"
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- name: shm
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: backend-webapp-srv-run
|
||||||
|
emptyDir: {}
|
||||||
|
- name: backend-webapp-srv-uploads
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: backend-uploads
|
||||||
|
- name: backend-admin-local-deps
|
||||||
|
configMap:
|
||||||
|
name: "backend-local-deps"
|
||||||
|
defaultMode: 0755
|
||||||
4
deployment/hotpocket_bthlab/resources/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: hotpocket-development
|
||||||
26
deployment/hotpocket_bthlab/resources/volumes.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: backend-uploads
|
||||||
|
namespace: hotpocket-development
|
||||||
|
spec:
|
||||||
|
storageClassName: nfs-client
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "1Gi"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: backend-celery-beat-run
|
||||||
|
namespace: hotpocket-development
|
||||||
|
spec:
|
||||||
|
storageClassName: nfs-client
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "1Gi"
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"default": {
|
"default": {
|
||||||
"targets": [
|
"targets": [
|
||||||
|
"apple-management",
|
||||||
"backend-management",
|
"backend-management",
|
||||||
"caddy",
|
"caddy",
|
||||||
"extension-management",
|
"extension-management",
|
||||||
@@ -13,6 +14,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
|
"apple-management": {
|
||||||
|
"context": "services/",
|
||||||
|
"dockerfile": "apple/Dockerfile",
|
||||||
|
"tags": [
|
||||||
|
"docker-hosted.nexus.bthlabs.pl/hotpocket/apple:local"
|
||||||
|
],
|
||||||
|
"target": "development",
|
||||||
|
"output": [
|
||||||
|
"type=docker,load=true,push=false"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"apple-ci": {
|
||||||
|
"context": "services/",
|
||||||
|
"dockerfile": "apple/Dockerfile",
|
||||||
|
"tags": [
|
||||||
|
"docker-hosted.nexus.bthlabs.pl/hotpocket/apple:ci-local"
|
||||||
|
],
|
||||||
|
"target": "ci",
|
||||||
|
"output": [
|
||||||
|
"type=docker,load=true,push=false"
|
||||||
|
]
|
||||||
|
},
|
||||||
"backend-management": {
|
"backend-management": {
|
||||||
"context": "services/",
|
"context": "services/",
|
||||||
"dockerfile": "backend/Dockerfile",
|
"dockerfile": "backend/Dockerfile",
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
ports: []
|
ports: !override []
|
||||||
|
|
||||||
keycloak:
|
keycloak:
|
||||||
command: "echo 'NOOP'"
|
command: "echo 'NOOP'"
|
||||||
ports: []
|
ports: !override []
|
||||||
restart: "no"
|
restart: "no"
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
ports: []
|
ports: !override []
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- path: "./services/backend/docker-compose-ci.yaml"
|
- path: "./services/backend/docker-compose-ci.yaml"
|
||||||
- path: "./services/packages/docker-compose-ci.yaml"
|
- path: "./services/packages/docker-compose-ci.yaml"
|
||||||
- path: "./services/extension/docker-compose-ci.yaml"
|
- path: "./services/extension/docker-compose-ci.yaml"
|
||||||
|
- path: "./services/apple/docker-compose-ci.yaml"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ include:
|
|||||||
- path: "./services/backend/docker-compose.yaml"
|
- path: "./services/backend/docker-compose.yaml"
|
||||||
- path: "./services/packages/docker-compose.yaml"
|
- path: "./services/packages/docker-compose.yaml"
|
||||||
- path: "./services/extension/docker-compose.yaml"
|
- path: "./services/extension/docker-compose.yaml"
|
||||||
|
- path: "./services/apple/docker-compose.yaml"
|
||||||
|
|
||||||
volumes: {}
|
volumes: {}
|
||||||
|
|
||||||
|
|||||||
20
poetry.lock
generated
@@ -1,16 +1,17 @@
|
|||||||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hotpocket-workspace-tools"
|
name = "hotpocket-workspace-tools"
|
||||||
version = "1.0.0.dev0"
|
version = "1.0.0.dev0"
|
||||||
description = "HotPocket Workspace Tools"
|
description = "HotPocket Workspace Tools"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.13"
|
||||||
|
groups = ["main"]
|
||||||
files = []
|
files = []
|
||||||
develop = true
|
develop = true
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
invoke = "2.2.0"
|
invoke = "2.2.1"
|
||||||
|
|
||||||
[package.source]
|
[package.source]
|
||||||
type = "directory"
|
type = "directory"
|
||||||
@@ -18,16 +19,17 @@ url = "services/packages/workspace_tools"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "invoke"
|
name = "invoke"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
description = "Pythonic task execution"
|
description = "Pythonic task execution"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"},
|
{file = "invoke-2.2.1-py3-none-any.whl", hash = "sha256:2413bc441b376e5cd3f55bb5d364f973ad8bdd7bf87e53c79de3c11bf3feecc8"},
|
||||||
{file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"},
|
{file = "invoke-2.2.1.tar.gz", hash = "sha256:515bf49b4a48932b79b024590348da22f39c4942dff991ad1fb8b8baea1be707"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.1"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.13"
|
||||||
content-hash = "ec33c3b3ec0f988e333872bdd134c1adce0782e98512dd2484cb85009b3da6cb"
|
content-hash = "175bf795c7148fe40af7e095d6f41918fa14cf4c71be87444a4d6c467fbd38d2"
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "hotpocket-workspace"
|
name = "hotpocket-workspace"
|
||||||
version = "25.10.4"
|
version = "25.11.26"
|
||||||
description = "HotPocket Workspace"
|
description = "HotPocket Workspace"
|
||||||
authors = ["Tomek Wójcik <contact@bthlabs.pl>"]
|
authors = ["Tomek Wójcik <contact@bthlabs.pl>"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
package-mode = false
|
package-mode = false
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.12"
|
python = "^3.13"
|
||||||
hotpocket-workspace-tools = {path = "services/packages/workspace_tools", develop = true}
|
hotpocket-workspace-tools = {path = "services/packages/workspace_tools", develop = true}
|
||||||
invoke = "2.2.0"
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
.mypy_cache/
|
||||||
|
.pytest_cache/
|
||||||
_tmp/
|
_tmp/
|
||||||
apple/
|
apple/build/
|
||||||
|
apple/DerivedData/
|
||||||
backend/node_modules/
|
backend/node_modules/
|
||||||
backend/ops/metal/
|
backend/ops/metal/
|
||||||
backend/hotpocket_backend/playground.py
|
backend/hotpocket_backend/playground.py
|
||||||
@@ -10,4 +13,5 @@ backend/hotpocket_backend/settings/metal/
|
|||||||
backend/hotpocket_backend/static/
|
backend/hotpocket_backend/static/
|
||||||
extension/node_modules/
|
extension/node_modules/
|
||||||
extension/dist/
|
extension/dist/
|
||||||
|
vendor/
|
||||||
.envrc*
|
.envrc*
|
||||||
|
|||||||
19
services/apple/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
ARG APP_USER_UID=1000
|
||||||
|
ARG APP_USER_GID=1000
|
||||||
|
ARG IMAGE_ID=development.00000000
|
||||||
|
|
||||||
|
FROM docker-hosted.nexus.bthlabs.pl/hotpocket/base:build-node-20251114-01 AS development
|
||||||
|
|
||||||
|
ARG APP_USER_UID
|
||||||
|
ARG APP_USER_GID
|
||||||
|
ARG IMAGE_ID
|
||||||
|
|
||||||
|
# COPY --chown=$APP_USER_UID:$APP_USER_GID apple/ops/bin/*.sh /srv/bin/
|
||||||
|
|
||||||
|
VOLUME ["/srv/node_modules", "/srv/venv"]
|
||||||
|
|
||||||
|
FROM development AS ci
|
||||||
|
|
||||||
|
COPY --chown=$APP_USER_UID:$APP_USER_GID apple/ /srv/app/
|
||||||
|
COPY --chown=$APP_USER_UID:$APP_USER_GID packages/ /srv/packages/
|
||||||
|
COPY --chown=$APP_USER_UID:$APP_USER_GID tls/ /srv/tls/
|
||||||
@@ -85,8 +85,8 @@
|
|||||||
4C70F3142E886A8F00320048 /* HPSharedItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HPSharedItem.m; sourceTree = "<group>"; };
|
4C70F3142E886A8F00320048 /* HPSharedItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HPSharedItem.m; sourceTree = "<group>"; };
|
||||||
4C70F3172E886ADD00320048 /* HPSharedItemsContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HPSharedItemsContainer.h; sourceTree = "<group>"; };
|
4C70F3172E886ADD00320048 /* HPSharedItemsContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HPSharedItemsContainer.h; sourceTree = "<group>"; };
|
||||||
4C70F3182E886ADD00320048 /* HPSharedItemsContainer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HPSharedItemsContainer.m; sourceTree = "<group>"; };
|
4C70F3182E886ADD00320048 /* HPSharedItemsContainer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HPSharedItemsContainer.m; sourceTree = "<group>"; };
|
||||||
4CABCAB02E56F0C900D8A354 /* HotPocket.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HotPocket.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
4CABCAB02E56F0C900D8A354 /* HotPocket Development.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "HotPocket Development.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
4CABCAC62E56F0C900D8A354 /* HotPocket.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HotPocket.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
4CABCAC62E56F0C900D8A354 /* HotPocket Development.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "HotPocket Development.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HotPocket Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HotPocket Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HotPocket Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HotPocket Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
4CBCEA4F2E81CB9500722009 /* Save to HotPocket.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Save to HotPocket.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
4CBCEA4F2E81CB9500722009 /* Save to HotPocket.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Save to HotPocket.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -107,6 +107,7 @@
|
|||||||
HPAPI.m,
|
HPAPI.m,
|
||||||
HPCredentialsHelper.m,
|
HPCredentialsHelper.m,
|
||||||
HPRPCClient.m,
|
HPRPCClient.m,
|
||||||
|
"NSBundle+HotPocketExtensions.m",
|
||||||
"NSURL+HotPocketExtensions.m",
|
"NSURL+HotPocketExtensions.m",
|
||||||
"Resources/icon-mac-384.png",
|
"Resources/icon-mac-384.png",
|
||||||
);
|
);
|
||||||
@@ -123,6 +124,7 @@
|
|||||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
membershipExceptions = (
|
membershipExceptions = (
|
||||||
MultilineLabel.m,
|
MultilineLabel.m,
|
||||||
|
UnameLabel.m,
|
||||||
);
|
);
|
||||||
target = 4C2F0C5D2E851BBD0033F5C2 /* iOS (Share Extension) */;
|
target = 4C2F0C5D2E851BBD0033F5C2 /* iOS (Share Extension) */;
|
||||||
};
|
};
|
||||||
@@ -134,6 +136,7 @@
|
|||||||
HPAuthFlow.m,
|
HPAuthFlow.m,
|
||||||
HPCredentialsHelper.m,
|
HPCredentialsHelper.m,
|
||||||
HPRPCClient.m,
|
HPRPCClient.m,
|
||||||
|
"NSBundle+HotPocketExtensions.m",
|
||||||
"NSURL+HotPocketExtensions.m",
|
"NSURL+HotPocketExtensions.m",
|
||||||
"Resources/icon-mac-384.png",
|
"Resources/icon-mac-384.png",
|
||||||
);
|
);
|
||||||
@@ -161,6 +164,7 @@
|
|||||||
HPAuthFlow.m,
|
HPAuthFlow.m,
|
||||||
HPCredentialsHelper.m,
|
HPCredentialsHelper.m,
|
||||||
HPRPCClient.m,
|
HPRPCClient.m,
|
||||||
|
"NSBundle+HotPocketExtensions.m",
|
||||||
"NSURL+HotPocketExtensions.m",
|
"NSURL+HotPocketExtensions.m",
|
||||||
"Resources/icon-mac-384.png",
|
"Resources/icon-mac-384.png",
|
||||||
);
|
);
|
||||||
@@ -215,6 +219,7 @@
|
|||||||
HPAPI.m,
|
HPAPI.m,
|
||||||
HPCredentialsHelper.m,
|
HPCredentialsHelper.m,
|
||||||
HPRPCClient.m,
|
HPRPCClient.m,
|
||||||
|
"NSBundle+HotPocketExtensions.m",
|
||||||
"NSURL+HotPocketExtensions.m",
|
"NSURL+HotPocketExtensions.m",
|
||||||
"Resources/icon-mac-384.png",
|
"Resources/icon-mac-384.png",
|
||||||
);
|
);
|
||||||
@@ -384,8 +389,8 @@
|
|||||||
4CABCAB12E56F0C900D8A354 /* Products */ = {
|
4CABCAB12E56F0C900D8A354 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4CABCAB02E56F0C900D8A354 /* HotPocket.app */,
|
4CABCAB02E56F0C900D8A354 /* HotPocket Development.app */,
|
||||||
4CABCAC62E56F0C900D8A354 /* HotPocket.app */,
|
4CABCAC62E56F0C900D8A354 /* HotPocket Development.app */,
|
||||||
4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */,
|
4CABCAD52E56F0C900D8A354 /* HotPocket Extension.appex */,
|
||||||
4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */,
|
4CABCADF2E56F0C900D8A354 /* HotPocket Extension.appex */,
|
||||||
4CBCEA4F2E81CB9500722009 /* Save to HotPocket.appex */,
|
4CBCEA4F2E81CB9500722009 /* Save to HotPocket.appex */,
|
||||||
@@ -441,7 +446,7 @@
|
|||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
);
|
);
|
||||||
productName = "HotPocket (iOS)";
|
productName = "HotPocket (iOS)";
|
||||||
productReference = 4CABCAB02E56F0C900D8A354 /* HotPocket.app */;
|
productReference = 4CABCAB02E56F0C900D8A354 /* HotPocket Development.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
4CABCAC52E56F0C900D8A354 /* HotPocket (macOS) */ = {
|
4CABCAC52E56F0C900D8A354 /* HotPocket (macOS) */ = {
|
||||||
@@ -466,7 +471,7 @@
|
|||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
);
|
);
|
||||||
productName = "HotPocket (macOS)";
|
productName = "HotPocket (macOS)";
|
||||||
productReference = 4CABCAC62E56F0C900D8A354 /* HotPocket.app */;
|
productReference = 4CABCAC62E56F0C900D8A354 /* HotPocket Development.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
4CABCAD42E56F0C900D8A354 /* HotPocket Extension (iOS) */ = {
|
4CABCAD42E56F0C900D8A354 /* HotPocket Extension (iOS) */ = {
|
||||||
@@ -713,7 +718,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = "iOS (Share Extension)/iOS (Share Extension).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "iOS (Share Extension)/iOS (Share Extension).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "iOS (Share Extension)/Info.plist";
|
INFOPLIST_FILE = "iOS (Share Extension)/Info.plist";
|
||||||
@@ -726,7 +731,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
||||||
PRODUCT_NAME = "Save to HotPocket";
|
PRODUCT_NAME = "Save to HotPocket";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -746,7 +751,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = "iOS (Share Extension)/iOS (Share Extension).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "iOS (Share Extension)/iOS (Share Extension).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "iOS (Share Extension)/Info.plist";
|
INFOPLIST_FILE = "iOS (Share Extension)/Info.plist";
|
||||||
@@ -759,7 +764,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
||||||
PRODUCT_NAME = "Save to HotPocket";
|
PRODUCT_NAME = "Save to HotPocket";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -779,7 +784,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
||||||
@@ -792,7 +797,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -814,7 +819,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
||||||
@@ -827,7 +832,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -853,7 +858,7 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "iOS (App)/HotPocket (iOS).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "iOS (App)/HotPocket (iOS).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
||||||
@@ -873,7 +878,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -881,7 +886,7 @@
|
|||||||
WebKit,
|
WebKit,
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
||||||
PRODUCT_NAME = HotPocket;
|
PRODUCT_NAME = "HotPocket Development";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
@@ -899,7 +904,7 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "iOS (App)/HotPocket (iOS).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "iOS (App)/HotPocket (iOS).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
||||||
@@ -919,7 +924,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -945,7 +950,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HotPocket.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HotPocket.entitlements";
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
@@ -960,7 +965,7 @@
|
|||||||
"@executable_path/../../../../Frameworks",
|
"@executable_path/../../../../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -980,7 +985,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HotPocket.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HotPocket.entitlements";
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
@@ -995,7 +1000,7 @@
|
|||||||
"@executable_path/../../../../Frameworks",
|
"@executable_path/../../../../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -1017,7 +1022,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "macOS (App)/HotPocket.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "macOS (App)/HotPocket.entitlements";
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -1033,7 +1038,7 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -1041,7 +1046,7 @@
|
|||||||
WebKit,
|
WebKit,
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket;
|
||||||
PRODUCT_NAME = HotPocket;
|
PRODUCT_NAME = "HotPocket Development";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
@@ -1056,7 +1061,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "macOS (App)/HotPocket.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "macOS (App)/HotPocket.entitlements";
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -1072,7 +1077,7 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-framework",
|
"-framework",
|
||||||
SafariServices,
|
SafariServices,
|
||||||
@@ -1206,7 +1211,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "macOS (Share Extension)/macOS (Share Extension).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "macOS (Share Extension)/macOS (Share Extension).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -1220,7 +1225,7 @@
|
|||||||
"@executable_path/../../../../Frameworks",
|
"@executable_path/../../../../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
||||||
PRODUCT_NAME = "Save to HotPocket";
|
PRODUCT_NAME = "Save to HotPocket";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
@@ -1236,7 +1241,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "macOS (Share Extension)/macOS (Share Extension).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "macOS (Share Extension)/macOS (Share Extension).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 2025100401;
|
CURRENT_PROJECT_VERSION = 2025112601;
|
||||||
DEVELOPMENT_TEAM = 648728X64K;
|
DEVELOPMENT_TEAM = 648728X64K;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -1250,7 +1255,7 @@
|
|||||||
"@executable_path/../../../../Frameworks",
|
"@executable_path/../../../../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 25.10.4;
|
MARKETING_VERSION = 25.11.26;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = pl.bthlabs.HotPocket.ShareExtension;
|
||||||
PRODUCT_NAME = "Save to HotPocket";
|
PRODUCT_NAME = "Save to HotPocket";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "icon-1024.png",
|
"filename" : "icon-ios-light.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"platform" : "ios",
|
"platform" : "ios",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"value" : "dark"
|
"value" : "dark"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"filename" : "icon-1024 1.png",
|
"filename" : "icon-ios-dark.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"platform" : "ios",
|
"platform" : "ios",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
@@ -25,31 +25,31 @@
|
|||||||
"value" : "tinted"
|
"value" : "tinted"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"filename" : "icon-1024 2.png",
|
"filename" : "icon-ios-tinted.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"platform" : "ios",
|
"platform" : "ios",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "icon-16.png",
|
"filename" : "icon-mac-16.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "16x16"
|
"size" : "16x16"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "icon-32.png",
|
"filename" : "icon-mac-32.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "16x16"
|
"size" : "16x16"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "icon-32 1.png",
|
"filename" : "icon-mac-32 1.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "32x32"
|
"size" : "32x32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "icon-64.png",
|
"filename" : "icon-mac-64.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "32x32"
|
"size" : "32x32"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 874 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 285 KiB |
|
After Width: | Height: | Size: 323 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 828 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 58 KiB |
@@ -10,6 +10,7 @@
|
|||||||
#import "HPAPI.h"
|
#import "HPAPI.h"
|
||||||
#import "HPCredentialsHelper.h"
|
#import "HPCredentialsHelper.h"
|
||||||
#import "HPRPCClient.h"
|
#import "HPRPCClient.h"
|
||||||
|
#import "NSBundle+HotPocketExtensions.h"
|
||||||
#import "NSURL+HotPocketExtensions.h"
|
#import "NSURL+HotPocketExtensions.h"
|
||||||
|
|
||||||
@implementation HPAuthParams
|
@implementation HPAuthParams
|
||||||
@@ -77,18 +78,19 @@
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary *postAuthenticateURLParams = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"HPAuthFlowPostAuthenticateURLParts"];
|
NSString *expectedScheme = [NSBundle postAuthenticateURLScheme];
|
||||||
if (postAuthenticateURLParams == nil) {
|
NSString *expectedHost = [NSBundle postAuthenticateURLHost];
|
||||||
|
if (expectedScheme == nil || expectedHost == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
|
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
|
||||||
|
|
||||||
if ([urlComponents.scheme isEqualToString:[postAuthenticateURLParams valueForKey:@"scheme"]] == NO) {
|
if ([urlComponents.scheme isEqualToString:expectedScheme] == NO) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([urlComponents.host isEqualToString:[postAuthenticateURLParams valueForKey:@"host"]] == NO) {
|
if ([urlComponents.host isEqualToString:expectedHost] == NO) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +111,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL)handleAuthParams:(HPAuthParams *)authParams {
|
-(BOOL)handleAuthParams:(HPAuthParams *)authParams {
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"AuthFlowDidReceiveAuthParams" object:self];
|
||||||
|
|
||||||
HPRPCClient *rpcClient = [[HPRPCClient alloc] initWithBaseURL:self.baseURL accessToken:nil];
|
HPRPCClient *rpcClient = [[HPRPCClient alloc] initWithBaseURL:self.baseURL accessToken:nil];
|
||||||
|
|
||||||
NSArray *callParams = @[
|
NSArray *callParams = @[
|
||||||
@@ -120,7 +124,7 @@
|
|||||||
method:@"accounts.access_tokens.create"
|
method:@"accounts.access_tokens.create"
|
||||||
params:callParams endopoint:@"/accounts/rpc/"
|
params:callParams endopoint:@"/accounts/rpc/"
|
||||||
completionHandler:^(NSString *callId, HPRPCCallResult *result) {
|
completionHandler:^(NSString *callId, HPRPCCallResult *result) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
if (result.error != nil) {
|
if (result.error != nil) {
|
||||||
NSLog(@"-[HPAuthFlow handleAuthParams:] error=`%@`", result.error);
|
NSLog(@"-[HPAuthFlow handleAuthParams:] error=`%@`", result.error);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
21
services/apple/Shared (App)/NSBundle+HotPocketExtensions.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// NSBundle+HotPocketExtensions.h
|
||||||
|
// HotPocket
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 17/11/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface NSBundle (HotPocketExtensions)
|
||||||
|
|
||||||
|
+(NSString *)uname;
|
||||||
|
+(NSDictionary *)postAuthenticateURLParams;
|
||||||
|
+(NSString *)postAuthenticateURLScheme;
|
||||||
|
+(NSString *)postAuthenticateURLHost;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
36
services/apple/Shared (App)/NSBundle+HotPocketExtensions.m
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// NSBundle+HotPocketExtensions.m
|
||||||
|
// HotPocket
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 17/11/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSBundle+HotPocketExtensions.h"
|
||||||
|
|
||||||
|
@implementation NSBundle (HotPocketExtensions)
|
||||||
|
|
||||||
|
+(NSString *)uname {
|
||||||
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||||
|
return [NSString stringWithFormat:@"HotPocket v%@ (%@)", [mainBundle.infoDictionary valueForKey:@"CFBundleShortVersionString"], [mainBundle.infoDictionary valueForKey:@"CFBundleVersion"]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+(NSDictionary *)postAuthenticateURLParams {
|
||||||
|
NSDictionary *result = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"HPAuthFlowPostAuthenticateURLParts"];
|
||||||
|
if (result == nil) {
|
||||||
|
return [NSDictionary dictionary];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+(NSString *)postAuthenticateURLScheme {
|
||||||
|
NSDictionary *params = [self postAuthenticateURLParams];
|
||||||
|
return [params valueForKey:@"scheme"];
|
||||||
|
}
|
||||||
|
|
||||||
|
+(NSString *)postAuthenticateURLHost {
|
||||||
|
NSDictionary *params = [self postAuthenticateURLParams];
|
||||||
|
return [params valueForKey:@"host"];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 68 KiB |
@@ -5,10 +5,10 @@
|
|||||||
// Created by Tomek Wójcik on 21/08/2025.
|
// Created by Tomek Wójcik on 21/08/2025.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "SafariWebExtensionHandler.h"
|
|
||||||
|
|
||||||
#import <SafariServices/SafariServices.h>
|
#import <SafariServices/SafariServices.h>
|
||||||
|
|
||||||
|
#import "SafariWebExtensionHandler.h"
|
||||||
|
|
||||||
@implementation SafariWebExtensionHandler
|
@implementation SafariWebExtensionHandler
|
||||||
|
|
||||||
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
|
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
|
||||||
|
|||||||
23
services/apple/docker-compose-ci.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
services:
|
||||||
|
apple-ci:
|
||||||
|
build:
|
||||||
|
context: ".."
|
||||||
|
dockerfile: "apple/Dockerfile"
|
||||||
|
target: "development"
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/apple:ci-local"
|
||||||
|
command: "echo 'NOOP'"
|
||||||
|
environment:
|
||||||
|
PYTHONBREAKPOINT: "ipdb.set_trace"
|
||||||
|
HOTPOCKET_PACKAGES_ENV: "${HOTPOCKET_EXTENSION_ENV:-docker}"
|
||||||
|
# REQUESTS_CA_BUNDLE: "/srv/tls/requests_ca_bundle.pem"
|
||||||
|
RUN_POETRY_INSTALL: "true"
|
||||||
|
RUN_YARN_INSTALL: "false"
|
||||||
|
SETUP_BACKEND: "true"
|
||||||
|
SETUP_FRONTEND: "false"
|
||||||
|
volumes:
|
||||||
|
- "apple_venv:/srv/venv"
|
||||||
|
- "apple_node_modules:/srv/node_modules"
|
||||||
|
- "../tls:/srv/tls"
|
||||||
|
restart: "no"
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
29
services/apple/docker-compose.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
services:
|
||||||
|
apple-management:
|
||||||
|
build:
|
||||||
|
context: ".."
|
||||||
|
dockerfile: "apple/Dockerfile"
|
||||||
|
target: "development"
|
||||||
|
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/apple:local"
|
||||||
|
command: "echo 'NOOP'"
|
||||||
|
environment: &apple-env
|
||||||
|
PYTHONBREAKPOINT: "ipdb.set_trace"
|
||||||
|
HOTPOCKET_EXTENSION_ENV: "${HOTPOCKET_EXTENSION_ENV:-docker}"
|
||||||
|
REQUESTS_CA_BUNDLE: "/srv/tls/requests_ca_bundle.pem"
|
||||||
|
RUN_POETRY_INSTALL: "true"
|
||||||
|
RUN_YARN_INSTALL: "false"
|
||||||
|
SETUP_BACKEND: "true"
|
||||||
|
SETUP_FRONTEND: "false"
|
||||||
|
volumes:
|
||||||
|
- "apple_venv:/srv/venv"
|
||||||
|
- "apple_node_modules:/srv/node_modules"
|
||||||
|
- ".:/srv/app"
|
||||||
|
- "../packages:/srv/packages"
|
||||||
|
- "../tls:/srv/tls"
|
||||||
|
restart: "no"
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
apple_venv:
|
||||||
|
apple_node_modules:
|
||||||
@@ -6,12 +6,19 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <AuthenticationServices/AuthenticationServices.h>
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface AuthorizationProgressViewController : UIViewController
|
@class MultilineLabel;
|
||||||
|
|
||||||
|
@interface AuthorizationProgressViewController : UIViewController<ASWebAuthenticationPresentationContextProviding>
|
||||||
|
|
||||||
@property IBOutlet UIActivityIndicatorView *progressIndicator;
|
@property IBOutlet UIActivityIndicatorView *progressIndicator;
|
||||||
|
@property IBOutlet MultilineLabel *progressLabel;
|
||||||
|
@property (strong, nullable) NSURL *authorizationURL;
|
||||||
|
@property (strong, nullable) ASWebAuthenticationSession *webAuthenticationSession;
|
||||||
|
@property BOOL userCancelledSession;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -8,20 +8,36 @@
|
|||||||
#import "AuthorizationProgressViewController.h"
|
#import "AuthorizationProgressViewController.h"
|
||||||
|
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
#import "HPAuthFlow.h"
|
||||||
#import "HPCredentialsHelper.h"
|
#import "HPCredentialsHelper.h"
|
||||||
|
#import "MultilineLabel.h"
|
||||||
|
#import "NSBundle+HotPocketExtensions.h"
|
||||||
|
|
||||||
@interface AuthorizationProgressViewController (AuthorizationProgressViewControllerPrivate)
|
@interface AuthorizationProgressViewController (AuthorizationProgressViewControllerPrivate)
|
||||||
|
|
||||||
#pragma mark - Private interface
|
#pragma mark - Private interface
|
||||||
|
|
||||||
|
-(void)presentAuthorizationError;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AuthorizationProgressViewController
|
@implementation AuthorizationProgressViewController
|
||||||
|
|
||||||
#pragma mark - View lifecycle
|
#pragma mark - View lifecycle
|
||||||
|
|
||||||
|
-(instancetype)initWithCoder:(NSCoder *)coder {
|
||||||
|
if (self = [super initWithCoder:coder]) {
|
||||||
|
self.authorizationURL = nil;
|
||||||
|
self.webAuthenticationSession = nil;
|
||||||
|
self.userCancelledSession = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
-(void)viewDidLoad {
|
-(void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
|
self.progressLabel.text = NSLocalizedString(@"Continue to sign in in your browser...", @"Continue to sign in in your browser...");
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)viewWillAppear:(BOOL)animated {
|
-(void)viewWillAppear:(BOOL)animated {
|
||||||
@@ -29,17 +45,90 @@
|
|||||||
[self.progressIndicator startAnimating];
|
[self.progressIndicator startAnimating];
|
||||||
|
|
||||||
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAuthFlowDidFinish:) name:@"AuthFlowDidFinish" object:appDelegate.authFlow];
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(onAuthFlowDidFinish:)
|
||||||
|
name:@"AuthFlowDidFinish"
|
||||||
|
object:appDelegate.authFlow];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(onAuthFlowDidReceiveAuthParams:)
|
||||||
|
name:@"AuthFlowDidReceiveAuthParams"
|
||||||
|
object:appDelegate.authFlow];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)viewWillDisappear:(BOOL)animated {
|
-(void)viewDidAppear:(BOOL)animated {
|
||||||
[super viewWillDisappear:animated];
|
[super viewDidAppear:animated];
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
||||||
|
|
||||||
|
ASWebAuthenticationSessionCompletionHandler completionHandler = ^(NSURL *url, NSError *error) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (error != nil) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSLog(@"[AuthorizationViewController.session completionHandler] error=`%@`", error);
|
||||||
|
#endif
|
||||||
|
if (error.code == ASWebAuthenticationSessionErrorCodeCanceledLogin) {
|
||||||
|
self.userCancelledSession = YES;
|
||||||
|
}
|
||||||
|
[self presentAuthorizationError];
|
||||||
|
} else {
|
||||||
|
HPAuthParams *receivedAuthParams = [appDelegate.authFlow handlePostAuthenticateURL:url];
|
||||||
|
if (receivedAuthParams != nil) {
|
||||||
|
[appDelegate.authFlow handleAuthParams:receivedAuthParams];
|
||||||
|
} else {
|
||||||
|
[self presentAuthorizationError];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.webAuthenticationSession = nil;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ASWebAuthenticationSessionCallback *callback = [ASWebAuthenticationSessionCallback callbackWithCustomScheme:[NSBundle postAuthenticateURLScheme]];
|
||||||
|
self.webAuthenticationSession = [[ASWebAuthenticationSession alloc] initWithURL:self.authorizationURL
|
||||||
|
callback:callback
|
||||||
|
completionHandler:completionHandler];
|
||||||
|
self.webAuthenticationSession.presentationContextProvider = self;
|
||||||
|
#ifdef DEBUG
|
||||||
|
self.webAuthenticationSession.prefersEphemeralWebBrowserSession = YES;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (self.webAuthenticationSession.canStart == NO) {
|
||||||
|
[self presentAuthorizationError];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.webAuthenticationSession start];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)viewDidDisappear:(BOOL)animated {
|
-(void)viewDidDisappear:(BOOL)animated {
|
||||||
[super viewDidDisappear:animated];
|
[super viewDidDisappear:animated];
|
||||||
|
self.webAuthenticationSession = nil;
|
||||||
|
|
||||||
[self.progressIndicator stopAnimating];
|
[self.progressIndicator stopAnimating];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
# pragma mark - Private interface
|
||||||
|
|
||||||
|
-(void)presentAuthorizationError {
|
||||||
|
if (self.userCancelledSession == NO) {
|
||||||
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Oops!", @"Oops!")
|
||||||
|
message:NSLocalizedString(@"HotPocket couldn't complete this operation.", @"HotPocket couldn't complete this operation.")
|
||||||
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Oh well", @"Oh well")
|
||||||
|
style:UIAlertActionStyleDefault
|
||||||
|
handler:^(UIAlertAction *action) {
|
||||||
|
[alert dismissViewControllerAnimated:YES completion:^{
|
||||||
|
[self.navigationController popViewControllerAnimated:YES];
|
||||||
|
}];
|
||||||
|
}]];
|
||||||
|
|
||||||
|
[self presentViewController:alert animated:YES completion:nil];
|
||||||
|
} else {
|
||||||
|
[self.navigationController popViewControllerAnimated:YES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Notification handlers
|
#pragma mark - Notification handlers
|
||||||
@@ -52,23 +141,21 @@
|
|||||||
HPCredentials *credentials = [[HPCredentialsHelper sharedHelper] getCredentials];
|
HPCredentials *credentials = [[HPCredentialsHelper sharedHelper] getCredentials];
|
||||||
|
|
||||||
if (credentials.usable == NO) {
|
if (credentials.usable == NO) {
|
||||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Oops!", @"Oops!")
|
[self presentAuthorizationError];
|
||||||
message:NSLocalizedString(@"HotPocket couldn't complete this operation.", @"HotPocket couldn't complete this operation.")
|
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Oh well", @"Oh well")
|
|
||||||
style:UIAlertActionStyleDefault
|
|
||||||
handler:^(UIAlertAction *action) {
|
|
||||||
[alert dismissViewControllerAnimated:YES completion:^{
|
|
||||||
[self.navigationController popViewControllerAnimated:YES];
|
|
||||||
}];
|
|
||||||
}]];
|
|
||||||
|
|
||||||
[self presentViewController:alert animated:YES completion:nil];
|
|
||||||
} else {
|
} else {
|
||||||
[self.navigationController popToRootViewControllerAnimated:YES];
|
[self.navigationController popToRootViewControllerAnimated:YES];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(void)onAuthFlowDidReceiveAuthParams:(NSNotification *)notification {
|
||||||
|
self.progressLabel.text = NSLocalizedString(@"Processing authorization...", @"Processing authorization...");
|
||||||
|
}
|
||||||
|
|
||||||
|
# pragma mark - ASWebAuthenticationPresentationContextProviding implementation
|
||||||
|
|
||||||
|
-(ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session {
|
||||||
|
return self.view.window;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,11 +9,14 @@
|
|||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@class UnameLabel;
|
||||||
|
|
||||||
@interface AuthorizationViewController : UIViewController
|
@interface AuthorizationViewController : UIViewController
|
||||||
|
|
||||||
@property UIImageView *invalidURLWarningView;
|
@property UIImageView *invalidURLWarningView;
|
||||||
|
|
||||||
@property IBOutlet UITextField *instanceURLField;
|
@property IBOutlet UITextField *instanceURLField;
|
||||||
|
@property IBOutlet UnameLabel *unameLabel;
|
||||||
|
|
||||||
-(IBAction)doStartAuthorizationFlow:(id)sender;
|
-(IBAction)doStartAuthorizationFlow:(id)sender;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
#import "HPAuthFlow.h"
|
#import "HPAuthFlow.h"
|
||||||
#import "HPCredentialsHelper.h"
|
#import "HPCredentialsHelper.h"
|
||||||
#import "MainViewController.h"
|
#import "MainViewController.h"
|
||||||
|
#import "NSBundle+HotPocketExtensions.h"
|
||||||
#import "NSURL+HotPocketExtensions.h"
|
#import "NSURL+HotPocketExtensions.h"
|
||||||
|
#import "UnameLabel.h"
|
||||||
|
|
||||||
@interface AuthorizationViewController (AuthorizationViewControllerPrivate)
|
@interface AuthorizationViewController (AuthorizationViewControllerPrivate)
|
||||||
|
|
||||||
@@ -31,6 +33,8 @@
|
|||||||
self.invalidURLWarningView.contentMode = UIViewContentModeScaleAspectFit;
|
self.invalidURLWarningView.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
self.invalidURLWarningView.frame = CGRectMake(0, 0, 16, 16);
|
self.invalidURLWarningView.frame = CGRectMake(0, 0, 16, 16);
|
||||||
self.invalidURLWarningView.tintColor = [UIColor colorNamed:@"WarningColor"];
|
self.invalidURLWarningView.tintColor = [UIColor colorNamed:@"WarningColor"];
|
||||||
|
|
||||||
|
self.unameLabel.text = [NSBundle uname];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)viewWillAppear:(BOOL)animated {
|
-(void)viewWillAppear:(BOOL)animated {
|
||||||
@@ -69,14 +73,9 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([application canOpenURL:authURL] == YES) {
|
AuthorizationProgressViewController *authorizationProgressViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"AuthorizationProgressViewController"];
|
||||||
[application openURL:authURL options:@{} completionHandler:^(BOOL result) {
|
authorizationProgressViewController.authorizationURL = authURL;
|
||||||
if (result == YES) {
|
[self.navigationController pushViewController:authorizationProgressViewController animated:YES];
|
||||||
AuthorizationProgressViewController *authorizationProgressViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"AuthorizationProgressViewController"];
|
|
||||||
[self.navigationController pushViewController:authorizationProgressViewController animated:YES];
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Event handlers
|
#pragma mark - Event handlers
|
||||||
|
|||||||
@@ -77,6 +77,13 @@
|
|||||||
<action selector="doLogOut:" destination="BYZ-38-t0r" eventType="primaryActionTriggered" id="iq7-wK-GMu"/>
|
<action selector="doLogOut:" destination="BYZ-38-t0r" eventType="primaryActionTriggered" id="iq7-wK-GMu"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SD4-ZJ-wLU" userLabel="uname Label" customClass="UnameLabel">
|
||||||
|
<rect key="frame" x="20" y="855" width="374" height="21"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
<color key="backgroundColor" name="BackgroundColor"/>
|
<color key="backgroundColor" name="BackgroundColor"/>
|
||||||
@@ -86,6 +93,7 @@
|
|||||||
<connections>
|
<connections>
|
||||||
<outlet property="instanceURLButton" destination="OPO-AY-zgd" id="1Wr-H9-eZ6"/>
|
<outlet property="instanceURLButton" destination="OPO-AY-zgd" id="1Wr-H9-eZ6"/>
|
||||||
<outlet property="logoutButton" destination="wQZ-n6-b0o" id="vco-vP-zvy"/>
|
<outlet property="logoutButton" destination="wQZ-n6-b0o" id="vco-vP-zvy"/>
|
||||||
|
<outlet property="unameLabel" destination="SD4-ZJ-wLU" id="LLk-wO-epu"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
@@ -136,7 +144,7 @@
|
|||||||
<action selector="doStartAuthorizationFlow:" destination="1Il-xJ-X5Y" eventType="primaryActionTriggered" id="Rd9-1f-N6Z"/>
|
<action selector="doStartAuthorizationFlow:" destination="1Il-xJ-X5Y" eventType="primaryActionTriggered" id="Rd9-1f-N6Z"/>
|
||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Enter the URL to your HotPocket instance, e.g. https://my.hotpocket.app" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tn1-fl-daL" customClass="MultilineLabel">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Enter the URL to your HotPocket instance, e.g. https://hotpocket.yourcompany.com/" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tn1-fl-daL" customClass="MultilineLabel">
|
||||||
<rect key="frame" x="20" y="348" width="374" height="64"/>
|
<rect key="frame" x="20" y="348" width="374" height="64"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
@@ -152,6 +160,13 @@
|
|||||||
<action selector="doStartAuthorizationFlow:" destination="1Il-xJ-X5Y" eventType="primaryActionTriggered" id="U0V-Pp-M2x"/>
|
<action selector="doStartAuthorizationFlow:" destination="1Il-xJ-X5Y" eventType="primaryActionTriggered" id="U0V-Pp-M2x"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gId-nt-VtS" userLabel="uname Label" customClass="UnameLabel">
|
||||||
|
<rect key="frame" x="20" y="855" width="374" height="21"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<viewLayoutGuide key="safeArea" id="dL2-4T-yXY"/>
|
<viewLayoutGuide key="safeArea" id="dL2-4T-yXY"/>
|
||||||
<color key="backgroundColor" name="BackgroundColor"/>
|
<color key="backgroundColor" name="BackgroundColor"/>
|
||||||
@@ -159,6 +174,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="instanceURLField" destination="v5s-Uh-qWU" id="hRQ-r8-3Dz"/>
|
<outlet property="instanceURLField" destination="v5s-Uh-qWU" id="hRQ-r8-3Dz"/>
|
||||||
|
<outlet property="unameLabel" destination="gId-nt-VtS" id="ust-gO-7YN"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="m6b-Bm-Ty7" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="m6b-Bm-Ty7" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||||
@@ -213,8 +229,8 @@
|
|||||||
<rect key="frame" x="189" y="306" width="37" height="37"/>
|
<rect key="frame" x="189" y="306" width="37" height="37"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Awaiting authentication response..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qiJ-yx-nMd">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Awaiting authentication response..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qiJ-yx-nMd" customClass="MultilineLabel">
|
||||||
<rect key="frame" x="20" y="359" width="374" height="21"/>
|
<rect key="frame" x="20" y="359" width="374" height="64"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
@@ -226,6 +242,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="progressIndicator" destination="DNy-gf-n60" id="hJF-jc-ZJ0"/>
|
<outlet property="progressIndicator" destination="DNy-gf-n60" id="hJF-jc-ZJ0"/>
|
||||||
|
<outlet property="progressLabel" destination="qiJ-yx-nMd" id="1Wu-em-XsK"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="N3D-cM-5Ro" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="N3D-cM-5Ro" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||||
|
|||||||
@@ -9,10 +9,13 @@
|
|||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@class UnameLabel;
|
||||||
|
|
||||||
@interface MainViewController : UIViewController
|
@interface MainViewController : UIViewController
|
||||||
|
|
||||||
@property IBOutlet UIButton *instanceURLButton;
|
@property IBOutlet UIButton *instanceURLButton;
|
||||||
@property IBOutlet UIButton *logoutButton;
|
@property IBOutlet UIButton *logoutButton;
|
||||||
|
@property IBOutlet UnameLabel *unameLabel;
|
||||||
|
|
||||||
-(IBAction)doOpenInstanceURL:(id)sender;
|
-(IBAction)doOpenInstanceURL:(id)sender;
|
||||||
-(IBAction)doLogOut:(id)sender;
|
-(IBAction)doLogOut:(id)sender;
|
||||||
|
|||||||
@@ -7,9 +7,10 @@
|
|||||||
|
|
||||||
#import "MainViewController.h"
|
#import "MainViewController.h"
|
||||||
|
|
||||||
#import "HPCredentialsHelper.h"
|
|
||||||
|
|
||||||
#import "AuthorizationViewController.h"
|
#import "AuthorizationViewController.h"
|
||||||
|
#import "HPCredentialsHelper.h"
|
||||||
|
#import "NSBundle+HotPocketExtensions.h"
|
||||||
|
#import "UnameLabel.h"
|
||||||
|
|
||||||
@interface MainViewController (MainViewControllerPrivate)
|
@interface MainViewController (MainViewControllerPrivate)
|
||||||
|
|
||||||
@@ -27,6 +28,8 @@
|
|||||||
[self.instanceURLButton setTitle:@"" forState:UIControlStateNormal];
|
[self.instanceURLButton setTitle:@"" forState:UIControlStateNormal];
|
||||||
self.instanceURLButton.enabled = NO;
|
self.instanceURLButton.enabled = NO;
|
||||||
|
|
||||||
|
self.unameLabel.text = [NSBundle uname];
|
||||||
|
|
||||||
self.logoutButton.enabled = NO;
|
self.logoutButton.enabled = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
services/apple/iOS (App)/UnameLabel.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// UnameLabel.h
|
||||||
|
// HotPocket
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 17/11/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface UnameLabel : UILabel
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
16
services/apple/iOS (App)/UnameLabel.m
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// UnameLabel.m
|
||||||
|
// HotPocket
|
||||||
|
//
|
||||||
|
// Created by Tomek Wójcik on 17/11/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "UnameLabel.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@implementation UnameLabel
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@class HPAPI;
|
@class HPAPI;
|
||||||
|
@class UnameLabel;
|
||||||
|
|
||||||
@interface ShareViewController : UIViewController
|
@interface ShareViewController : UIViewController
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
@property IBOutlet UIView *doneView;
|
@property IBOutlet UIView *doneView;
|
||||||
@property IBOutlet UIView *errorView;
|
@property IBOutlet UIView *errorView;
|
||||||
@property IBOutlet UIView *unprocessableEntityView;
|
@property IBOutlet UIView *unprocessableEntityView;
|
||||||
@property IBOutlet UILabel *unameLabel;
|
@property IBOutlet UnameLabel *unameLabel;
|
||||||
|
|
||||||
-(IBAction)doCancel:(id)sender;
|
-(IBAction)doCancel:(id)sender;
|
||||||
-(IBAction)doClose:(id)sender;
|
-(IBAction)doClose:(id)sender;
|
||||||
|
|||||||