Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • commul/oetzit
1 result
Select Git revision
Show changes
Commits on Source (36)
Showing
with 295 additions and 85 deletions
.gitsecret/keys/random_seed .gitsecret/keys/random_seed
!*.secret !*.secret
backend/k8s/overlays/stg/database.secrets.env backend/k8s/overlays/stg/*.secrets.env
backend/k8s/overlays/prd/database.secrets.env backend/k8s/overlays/prd/*.secrets.env
butler
butler.zip
7z.so
libc7zip.so
Makefile.env
kubeconfig.yml
...@@ -13,8 +13,8 @@ stages: ...@@ -13,8 +13,8 @@ stages:
.node-job: &node-job .node-job: &node-job
image: node:16-alpine image: node:16-alpine
tags: # tags:
- shared # - shared
only: only:
- pushes - pushes
...@@ -46,7 +46,7 @@ stages: ...@@ -46,7 +46,7 @@ stages:
#--[ Frontend ]----------------------------------------------------------------- #--[ Frontend ]-----------------------------------------------------------------
cache-fe-node-job: fe-cache-job:
extends: .fe-node-job extends: .fe-node-job
stage: setup stage: setup
script: script:
...@@ -54,59 +54,77 @@ cache-fe-node-job: ...@@ -54,59 +54,77 @@ cache-fe-node-job:
#--[ Backend ]------------------------------------------------------------------ #--[ Backend ]------------------------------------------------------------------
cache-be-node-job: be-cache-job:
extends: .be-node-job extends: .be-node-job
stage: setup stage: setup
script: script:
- echo "Done!" - echo "Done!"
#--[ Cetera ]-------------------------------------------------------------------
app-tagger-job:
stage: setup
variables:
GIT_STRATEGY: clone
GIT_DEPTH: 0
script:
- APP_VERSION=$(git describe --tags)
- echo Detected app version ${APP_VERSION}
- echo "APP_VERSION=$APP_VERSION" >> build.env
artifacts:
reports:
dotenv: build.env
only:
- tags
- development
#==[ CHECK STAGE ]============================================================== #==[ CHECK STAGE ]==============================================================
#--[ Frontend ]----------------------------------------------------------------- #--[ Frontend ]-----------------------------------------------------------------
.check-fe-node-job: &check-fe-node-job .fe-check-job: &fe-check-job
extends: .fe-node-job extends: .fe-node-job
stage: check stage: check
needs: needs:
- cache-fe-node-job - fe-cache-job
allow_failure: true # TODO: disallow! # allow_failure: true # TODO: disallow!
format-fe-node-job: fe-format-job:
<<: *check-fe-node-job <<: *fe-check-job
script: script:
- npm run format:check - npm run format:check
lint-fe-node-job: fe-lint-job:
<<: *check-fe-node-job <<: *fe-check-job
script: script:
- npm run lint:check - npm run lint:check
test-fe-node-job: fe-test-job:
<<: *check-fe-node-job <<: *fe-check-job
script: script:
- npm run test - npm run test
#--[ Backend ]------------------------------------------------------------------ #--[ Backend ]------------------------------------------------------------------
.check-be-node-job: &check-be-node-job .be-check-job: &be-check-job
extends: .be-node-job extends: .be-node-job
stage: check stage: check
needs: needs:
- cache-be-node-job - be-cache-job
allow_failure: true # TODO: disallow! # allow_failure: true # TODO: disallow!
format-be-node-job: be-format-job:
<<: *check-be-node-job <<: *be-check-job
script: script:
- npm run format:check - npm run format:check
lint-be-node-job: be-lint-job:
<<: *check-be-node-job <<: *be-check-job
script: script:
- npm run lint:check - npm run lint:check
test-be-node-job: be-test-job:
<<: *check-be-node-job <<: *be-check-job
script: script:
- npm run test - npm run test
...@@ -114,12 +132,11 @@ test-be-node-job: ...@@ -114,12 +132,11 @@ test-be-node-job:
#--[ Frontend ]----------------------------------------------------------------- #--[ Frontend ]-----------------------------------------------------------------
prd-build-fe-node-job: prd-fe-build-job:
extends: .fe-node-job extends: .fe-node-job
stage: build stage: build
variables: variables:
NODE_ENV: production NODE_ENV: production
APP_VERSION: ${CI_COMMIT_TAG}
ROLLBAR_ACCESS_TOKEN: $POST_CLIENT_ITEM_ROLLBAR_ACCESS_TOKEN ROLLBAR_ACCESS_TOKEN: $POST_CLIENT_ITEM_ROLLBAR_ACCESS_TOKEN
script: script:
- npm run build -- --dist-dir dist/prd - npm run build -- --dist-dir dist/prd
...@@ -130,12 +147,11 @@ prd-build-fe-node-job: ...@@ -130,12 +147,11 @@ prd-build-fe-node-job:
only: only:
- tags - tags
stg-build-fe-node-job: stg-fe-build-job:
extends: .fe-node-job extends: .fe-node-job
stage: build stage: build
variables: variables:
NODE_ENV: staging NODE_ENV: staging
APP_VERSION: ${CI_COMMIT_SHORT_SHA}
ROLLBAR_ACCESS_TOKEN: $POST_CLIENT_ITEM_ROLLBAR_ACCESS_TOKEN ROLLBAR_ACCESS_TOKEN: $POST_CLIENT_ITEM_ROLLBAR_ACCESS_TOKEN
script: script:
- npm run build -- --dist-dir dist/stg - npm run build -- --dist-dir dist/stg
...@@ -148,32 +164,49 @@ stg-build-fe-node-job: ...@@ -148,32 +164,49 @@ stg-build-fe-node-job:
#--[ Backend ]------------------------------------------------------------------ #--[ Backend ]------------------------------------------------------------------
# TODO: cache docker layers .be-build-job:
build-be-job:
image: docker:20.10.12
stage: build stage: build
tags: image:
- commul # NOTE: we need commul (not shared) because of credentials in environment name: gcr.io/kaniko-project/executor:debug
services: entrypoint: [""]
- docker:dind
variables: variables:
IMAGE_NAME: $CI_REGISTRY_IMAGE/backend IMAGE_NAME: $CI_REGISTRY_IMAGE/backend
before_script: before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN https://$CI_REGISTRY - mkdir -p /kaniko/.docker
script: - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
- >
docker build prd-be-build-job:
--rm --no-cache extends: .be-build-job
--target production stage: build
--tag=$IMAGE_NAME:${CI_COMMIT_SHA} script: >-
--tag=$IMAGE_NAME:${CI_COMMIT_REF_NAME} /kaniko/executor
--tag=$IMAGE_NAME:${CI_COMMIT_TAG:-latest} --context "${CI_PROJECT_DIR}/backend"
--build-arg APP_VERSION=${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA} --dockerfile "${CI_PROJECT_DIR}/backend/Dockerfile"
--build-arg ROLLBAR_ACCESS_TOKEN=$POST_SERVER_ITEM_ROLLBAR_ACCESS_TOKEN --target production
backend --destination ${CI_REGISTRY_IMAGE}/backend:latest
- docker image push --all-tags $IMAGE_NAME --destination ${CI_REGISTRY_IMAGE}/backend:${APP_VERSION}
--destination ${CI_REGISTRY_IMAGE}/backend:${APP_VERSION%.*}
--destination ${CI_REGISTRY_IMAGE}/backend:${APP_VERSION%%.*}
--destination ${CI_REGISTRY_IMAGE}/backend:${CI_COMMIT_SHA}
--build-arg APP_VERSION=$APP_VERSION
--build-arg ROLLBAR_ACCESS_TOKEN=$POST_SERVER_ITEM_ROLLBAR_ACCESS_TOKEN
only: only:
- tags - tags
stg-be-build-job:
extends: .be-build-job
stage: build
script: >-
/kaniko/executor
--context "${CI_PROJECT_DIR}/backend"
--dockerfile "${CI_PROJECT_DIR}/backend/Dockerfile"
--target production
--destination ${CI_REGISTRY_IMAGE}/backend:${CI_COMMIT_REF_NAME}
--destination ${CI_REGISTRY_IMAGE}/backend:${APP_VERSION}
--destination ${CI_REGISTRY_IMAGE}/backend:${CI_COMMIT_SHA}
--build-arg APP_VERSION=$APP_VERSION
--build-arg ROLLBAR_ACCESS_TOKEN=$POST_SERVER_ITEM_ROLLBAR_ACCESS_TOKEN
only:
- development - development
#==[ DEPLOY STAGE ]============================================================= #==[ DEPLOY STAGE ]=============================================================
...@@ -183,8 +216,9 @@ build-be-job: ...@@ -183,8 +216,9 @@ build-be-job:
.fe-deploy-job: .fe-deploy-job:
image: alpine:latest image: alpine:latest
stage: deploy stage: deploy
tags: # tags:
- commul # NOTE: we can't use shared because extended seccomp policies are needed # - shared
# - commul # NOTE: we used to require commul because extended seccomp policies are needed
before_script: before_script:
- ./ci/install-butler-on-alpine.sh - ./ci/install-butler-on-alpine.sh
script: script:
...@@ -192,12 +226,13 @@ build-be-job: ...@@ -192,12 +226,13 @@ build-be-job:
butler push butler push
$DIST_PATH $DIST_PATH
eurac/$GAME_NAME:html5 eurac/$GAME_NAME:html5
--userversion ${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA} --userversion ${USER_VERSION}
prd-fe-deploy-job: prd-fe-deploy-job:
extends: .fe-deploy-job extends: .fe-deploy-job
needs: needs:
- job: prd-build-fe-node-job - app-tagger-job
- job: prd-fe-build-job
artifacts: true artifacts: true
environment: environment:
name: production/frontend name: production/frontend
...@@ -206,13 +241,15 @@ prd-fe-deploy-job: ...@@ -206,13 +241,15 @@ prd-fe-deploy-job:
variables: variables:
GAME_NAME: oetzit GAME_NAME: oetzit
DIST_PATH: frontend/dist/prd DIST_PATH: frontend/dist/prd
USER_VERSION: ${APP_VERSION}
only: only:
- tags - tags
stg-fe-deploy-job: stg-fe-deploy-job:
extends: .fe-deploy-job extends: .fe-deploy-job
needs: needs:
- job: stg-build-fe-node-job - app-tagger-job
- job: stg-fe-build-job
artifacts: true artifacts: true
environment: environment:
name: staging/frontend name: staging/frontend
...@@ -221,6 +258,7 @@ stg-fe-deploy-job: ...@@ -221,6 +258,7 @@ stg-fe-deploy-job:
variables: variables:
GAME_NAME: oetzit-staging GAME_NAME: oetzit-staging
DIST_PATH: frontend/dist/stg DIST_PATH: frontend/dist/stg
USER_VERSION: ${APP_VERSION}
only: only:
- development - development
...@@ -229,20 +267,19 @@ stg-fe-deploy-job: ...@@ -229,20 +267,19 @@ stg-fe-deploy-job:
.be-deploy-job: .be-deploy-job:
image: alpine:latest image: alpine:latest
stage: deploy stage: deploy
needs:
- job: build-be-job
artifacts: false
tags:
- shared
variables: variables:
IMAGE_NAME: $CI_REGISTRY_IMAGE/backend IMAGE_NAME: $CI_REGISTRY_IMAGE/backend
before_script: before_script:
- ./ci/install-kubectl-on-alpine.sh - ./ci/install-kubectl-on-alpine.sh
script: script:
- kubectl set image deployment/${K8S_DEPLOYMENT} oetzit=${IMAGE_NAME}:${CI_COMMIT_SHA} --namespace=${K8S_NAMESPACE} - kubectl set image deployment/${K8S_DEPLOYMENT} oetzit=${IMAGE_NAME}:${APP_VERSION} --namespace=${K8S_NAMESPACE}
prd-be-deploy-job: prd-be-deploy-job:
extends: .be-deploy-job extends: .be-deploy-job
needs:
- app-tagger-job
- job: prd-be-build-job
artifacts: false
environment: environment:
name: production/backend name: production/backend
deployment_tier: production deployment_tier: production
...@@ -255,6 +292,10 @@ prd-be-deploy-job: ...@@ -255,6 +292,10 @@ prd-be-deploy-job:
stg-be-deploy-job: stg-be-deploy-job:
extends: .be-deploy-job extends: .be-deploy-job
needs:
- app-tagger-job
- job: stg-be-build-job
artifacts: false
environment: environment:
name: staging/backend name: staging/backend
deployment_tier: staging deployment_tier: staging
......
backend/k8s/overlays/stg/database.secrets.env:20315cecd8ffc0b934acfdd6fc7b5c8761a9f7324f61b22df655e9897f97df62 backend/k8s/overlays/stg/database.secrets.env:20315cecd8ffc0b934acfdd6fc7b5c8761a9f7324f61b22df655e9897f97df62
backend/k8s/overlays/prd/database.secrets.env:21029ab07d6110a9bfc1b641bb921c7cd6344a4894f87033a79bc9b1955644df backend/k8s/overlays/prd/database.secrets.env:21029ab07d6110a9bfc1b641bb921c7cd6344a4894f87033a79bc9b1955644df
Makefile.env
kubeconfig.yml
backend/k8s/overlays/prd/dashboard.secrets.env
backend/k8s/overlays/stg/dashboard.secrets.env
...@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [1.4.0] - 2022-05-30
### Added
- `FE` Caps lock now works properly on desktop.
- `FE` Track best level.
- `FE` Best (and last) level, score, time and word count are all tracked in `Record` component.
### Changed
- `BE` Migrations now run in an `initContainer` automatically upon deployment.
- `BE`/`FE` Improved tagging and deployment strategies.
### Fixed
- `FE` Removed music jumps at scene changes.
## [1.3.0] - 2022-05-18 ## [1.3.0] - 2022-05-18
### Added ### Added
...@@ -241,7 +258,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -241,7 +258,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- POC by [Giovanni Moretti](https://www.giovannimoretti.it/). - POC by [Giovanni Moretti](https://www.giovannimoretti.it/).
[unreleased]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.2.0...development [unreleased]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.4.0...development
[1.4.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.3.0...1.4.0
[1.3.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.2.0...1.3.0
[1.2.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.1.0...1.2.0 [1.2.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.1.0...1.2.0
[1.1.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.0.0...1.1.0 [1.1.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/1.0.0...1.1.0
[1.0.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/0.7.0...1.0.0 [1.0.0]: https://gitlab.inf.unibz.it/commul/oetzit/compare/0.7.0...1.0.0
......
include Makefile.env
APP_VERSION := $(shell git describe --tags)
CI_COMMIT_SHA := $(shell git rev-parse HEAD)
# BE HELPERS
docker-login:
docker login \
-u ${CI_REGISTRY_USER} \
-p ${CI_JOB_TOKEN} \
https://${CI_REGISTRY}
docker-build:
docker build \
--target production \
--tag=${IMAGE_NAME}:${APP_VERSION} \
--tag=${IMAGE_NAME}:${CI_COMMIT_SHA} \
--build-arg APP_VERSION=${APP_VERSION} \
--build-arg ROLLBAR_ACCESS_TOKEN=${POST_SERVER_ITEM_ROLLBAR_ACCESS_TOKEN} \
backend
docker-push:
docker image push --all-tags ${IMAGE_NAME}
# BE JOBS
build-be-job: docker-login docker-build docker-push
stg-be-deploy-job:
kubectl set image \
deployment/${K8S_DEPLOYMENT} \
oetzit=${IMAGE_NAME}:${CI_COMMIT_SHA} \
--namespace=kommul-dev
prd-be-deploy-job:
kubectl set image \
deployment/${K8S_DEPLOYMENT} \
oetzit=${IMAGE_NAME}:${CI_COMMIT_SHA} \
--namespace=kommul
# FE HELPERS
get-butler:
wget -O butler.zip ${BUTLER_URL}
unzip butler.zip
chmod +x tmp/butler
./butler -V
# FE JOBS
stg-build-fe-node-job:
rm -rf frontend/dist/stg
cd frontend && \
NODE_ENV=staging \
npm run build -- --dist-dir dist/stg
prd-build-fe-node-job:
rm -rf frontend/dist/prd
cd frontend && \
NODE_ENV=production \
npm run build -- --dist-dir dist/prd
stg-fe-deploy-job:
./butler push \
frontend/dist/stg \
eurac/oetzit-staging:html5 \
--userversion ${APP_VERSION}
prd-fe-deploy-job:
./butler push \
frontend/dist/prd \
eurac/oetzit:html5 \
--userversion ${APP_VERSION}
coverage coverage
dist dist
node_modules node_modules
postgres-data
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",
"prettier" "prettier"
], ],
"globals": { "document": true, "Chart": true },
"rules": { "rules": {
"prettier/prettier": 2 "prettier/prettier": 2
}, },
......
...@@ -14,7 +14,13 @@ spec: ...@@ -14,7 +14,13 @@ spec:
- name: http - name: http
containerPort: 80 containerPort: 80
command: ["npm", "run", "serve"] command: ["npm", "run", "serve"]
env: env: &env
- name: PORT - name: PORT
value: "80" value: "80"
- name: DATABASE_URL - name: DATABASE_URL
initContainers:
- name: oetzit-migrator
image: oetzit-webserver-image
resources: {}
command: ["npm", "exec", "knex", "migrate:latest"]
env: *env # TODO: use configMap?
...@@ -23,3 +23,8 @@ secretGenerator: ...@@ -23,3 +23,8 @@ secretGenerator:
- url=postgres://db_user:db_pass@oetzit-database-service/db_name - url=postgres://db_user:db_pass@oetzit-database-service/db_name
name: oetzit-database-credentials name: oetzit-database-credentials
type: Opaque type: Opaque
- literals:
- username=admin
- password=admin
name: oetzit-dashboard-credentials
type: Opaque
...@@ -8,9 +8,23 @@ spec: ...@@ -8,9 +8,23 @@ spec:
containers: containers:
- name: oetzit - name: oetzit
imagePullPolicy: Never imagePullPolicy: Never
env: env: &env
- name: DATABASE_URL - name: DATABASE_URL
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: oetzit-database-credentials name: oetzit-database-credentials
key: url key: url
- name: DASHBOARD_USERNAME
valueFrom:
secretKeyRef:
name: oetzit-dashboard-credentials
key: username
- name: DASHBOARD_PASSWORD
valueFrom:
secretKeyRef:
name: oetzit-dashboard-credentials
key: password
initContainers: # TODO: use job?
- name: oetzit-migrator
imagePullPolicy: Always
env: *env # TODO: use configMap?
...@@ -20,3 +20,7 @@ secretGenerator: ...@@ -20,3 +20,7 @@ secretGenerator:
- database.secrets.env - database.secrets.env
name: oetzit-database-credentials name: oetzit-database-credentials
type: Opaque type: Opaque
- envs:
- dashboard.secrets.env
name: oetzit-dashboard-credentials
type: Opaque
...@@ -8,9 +8,23 @@ spec: ...@@ -8,9 +8,23 @@ spec:
containers: containers:
- name: oetzit - name: oetzit
imagePullPolicy: Always imagePullPolicy: Always
env: env: &env
- name: DATABASE_URL - name: DATABASE_URL
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: oetzit-database-credentials name: oetzit-database-credentials
key: url key: url
- name: DASHBOARD_USERNAME
valueFrom:
secretKeyRef:
name: oetzit-dashboard-credentials
key: username
- name: DASHBOARD_PASSWORD
valueFrom:
secretKeyRef:
name: oetzit-dashboard-credentials
key: password
initContainers: # TODO: use job?
- name: oetzit-migrator
imagePullPolicy: Always
env: *env # TODO: use configMap?
...@@ -14,9 +14,13 @@ patchesStrategicMerge: ...@@ -14,9 +14,13 @@ patchesStrategicMerge:
images: images:
- name: oetzit-webserver-image - name: oetzit-webserver-image
newName: gitlab.inf.unibz.it:4567/commul/oetzit/backend newName: gitlab.inf.unibz.it:4567/commul/oetzit/backend
newTag: latest newTag: development
secretGenerator: secretGenerator:
- envs: - envs:
- database.secrets.env - database.secrets.env
name: oetzit-database-credentials name: oetzit-database-credentials
type: Opaque type: Opaque
- envs:
- dashboard.secrets.env
name: oetzit-dashboard-credentials
type: Opaque
...@@ -8,9 +8,23 @@ spec: ...@@ -8,9 +8,23 @@ spec:
containers: containers:
- name: oetzit - name: oetzit
imagePullPolicy: Always imagePullPolicy: Always
env: env: &env
- name: DATABASE_URL - name: DATABASE_URL
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: oetzit-database-credentials name: oetzit-database-credentials
key: url key: url
- name: DASHBOARD_USERNAME
valueFrom:
secretKeyRef:
name: oetzit-dashboard-credentials
key: username
- name: DASHBOARD_PASSWORD
valueFrom:
secretKeyRef:
name: oetzit-dashboard-credentials
key: password
initContainers: # TODO: use job?
- name: oetzit-migrator
imagePullPolicy: Always
env: *env # TODO: use configMap?
{ {
"name": "oetzit-backend", "name": "oetzit-backend",
"version": "1.2.0", "version": "1.4.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "oetzit-backend", "name": "oetzit-backend",
"version": "1.2.0", "version": "1.4.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@fastify/auth": "^2.0.0", "@fastify/auth": "^2.0.0",
......
{ {
"name": "oetzit-backend", "name": "oetzit-backend",
"version": "1.3.0", "version": "1.4.0",
"description": "Ötzit! backend.", "description": "Ötzit! backend.",
"license": "MIT", "license": "MIT",
"author": { "author": {
......
{ {
"name": "oetzit-backend", "name": "oetzit-backend",
"version": "1.2.0", "version": "1.4.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "oetzit-backend", "name": "oetzit-backend",
"version": "1.2.0", "version": "1.4.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^0.26.0", "axios": "^0.26.0",
......
{ {
"name": "oetzit-backend", "name": "oetzit-backend",
"version": "1.3.0", "version": "1.4.0",
"description": "Ötzit! frontend.", "description": "Ötzit! frontend.",
"license": "MIT", "license": "MIT",
"author": { "author": {
......
...@@ -39,7 +39,10 @@ $key-width: 8vw; // 100/12 ~ 8.3 ...@@ -39,7 +39,10 @@ $key-width: 8vw; // 100/12 ~ 8.3
} }
&:nth-child(3) { &:nth-child(3) {
grid-template-columns: 2.333 * $key-width repeat(8, $key-width) 1fr; grid-template-columns: 2.333 * $key-width repeat(8, $key-width) 1fr;
& > :first-child { display: none; } & > :nth-child(1),
& > :nth-child(2) {
display: none;
}
} }
} }
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="css/main.scss" rel="stylesheet" />
<script type="module" src="js/rollbar.ts"></script>
<script type="module" src="js/main.ts"></script>
<title>Ötzit!</title>
</head>
<head> <body>
<meta charset="utf-8"> <div class="simple-keyboard"></div>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> </body>
<link href="css/main.scss" rel="stylesheet">
<script type="module" src="js/rollbar.ts"></script>
<script type="module" src="js/main.ts"></script>
<title>Ötzit!</title>
</head>
<body>
<div class="simple-keyboard"></div>
</body>
</html> </html>