Вступление

Привет, Хабр! Это мой первый пост на данной площадке, давно читаю, но писать все не решался, но, как говорится, когда-то все в жизни бывает в первый раз.

Коротко о том, что будет в статье

  • быстро настроим Gitlab для имитации CI-CD как у взрослых дядь (образно выражаясь)

  • напишем простое Hello world web-приложение (без излишеств, максимально быстро и просто)

  • превратим наше web-приложение в Android-приложение при помощи Cordova (как мне кажется, самый простой метод, для не вовлеченных в индустрию людей)

  • соберем тестовую версию .apk приложения и запустим на Android-телефоне

Дисклеймер

Web- и Android-разработка не являются моими прямыми должностными обязанностями, это мое хобби, на которое я предпочитаю тратить свободное от работы и прочих дел время, я понимаю, что в некоторых случаях могу показать антипаттерн в методах реализации демонстрационного проекта. Надеюсь, вы подсветите мне все нюансы в комментариях! Цель статьи — показать общую концепцию одного из вариантов реализации конвейера для быстрого выпуска простых Android-приложений

Глава 1. Gitlab CI-CD

Основная задача на данном этапе — получить локальный инстанс Gitlab-CE и раннеры для того, чтобы можно было хранить наш код, иметь систему контроля версий и быстро собирать продукт из исходников.

Воспользуемся контейнеризацией (Docker + Docker Compose) для того, чтобы упростить процесс деплоя Gitlab на локальную машину, нам понадобится собственно Gitlab-CE и несколько раннеров (в моем примере — 3), для того чтобы не только хранить код, но и собирать проект (таблица 1).

таблица 1 — Используемые образы

Наименование

Ссылка на Docker hub

Описание

Gitlab-CE

https://hub.docker.com/r/gitlab/gitlab-ce

gitlab-ce server 16.1.0-ce.0

Gitlab Runner

https://hub.docker.com/r/gitlab/gitlab-runner

gitlab build runner alpine3.18-v16.1.0 shell

Для того чтобы иметь возможность тестировать код и собирать web- и android-приложения, нам понадобится модифицировать образ Gitlab Runner под свои нужды; так как мы взяли за основу версию Alpine, сделать это будет совсем просто, напишем простой Dockerfile, для того чтобы добавить все необходимое:

FROM gitlab/gitlab-runner:alpine3.18-v16.1.0

# set LANG env var
ENV LANG=C.UTF-8

#add Glibc 2.34 for Alpine linux
RUN ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" && \
    ALPINE_GLIBC_PACKAGE_VERSION="2.34-r0" && \
    ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    apk add --no-cache --virtual=.build-dependencies wget ca-certificates && \
    echo \
        "-----BEGIN PUBLIC KEY-----\
        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZ2u1KJKUu/fW4A25y9m\
        y70AGEa/J3Wi5ibNVGNn1gT1r0VfgeWd0pUybS4UmcHdiNzxJPgoWQhV2SSW1JYu\
        tOqKZF5QSN6X937PTUpNBjUvLtTQ1ve1fp39uf/lEXPpFpOPL88LKnDBgbh7wkCp\
        m2KzLVGChf83MS0ShL6G9EQIAUxLm99VpgRjwqTQ/KfzGtpke1wqws4au0Ab4qPY\
        KXvMLSPLUp7cfulWvhmZSegr5AdhNw5KNizPqCJT8ZrGvgHypXyiFvvAH5YRtSsc\
        Zvo9GI2e2MaZyo9/lvb+LbLEJZKEQckqRj4P26gmASrZEPStwc+yqy1ShHLA0j6m\
        1QIDAQAB\
        -----END PUBLIC KEY-----" | sed 's/   */\n/g' > "/etc/apk/keys/sgerrand.rsa.pub" && \
    wget \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    mv /etc/nsswitch.conf /etc/nsswitch.conf.bak && \
    apk add --no-cache --force-overwrite \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    \
    mv /etc/nsswitch.conf.bak /etc/nsswitch.conf && \
    rm "/etc/apk/keys/sgerrand.rsa.pub" && \
    (/usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true) && \
    echo "export LANG=$LANG" > /etc/profile.d/locale.sh && \
    \
    apk del glibc-i18n && \
    \
    rm "/root/.wget-hsts" && \
    apk del .build-dependencies && \
    rm \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME"

# set env vars
ENV ANDROID_SDK_ROOT "/opt/sdk"
ENV ANDROID_HOME ${ANDROID_SDK_ROOT}
ENV PATH $PATH:${ANDROID_SDK_ROOT}/gradle/6.5/bin:${ANDROID_SDK_ROOT}/cmdline-tools/latest_supported/bin:${ANDROID_SDK_ROOT}/platform-tools:${ANDROID_SDK_ROOT}/extras/google/instantapps:${ANDROID_SDK_ROOT}/build-tools/34.0.0

# add core apps and libs (jdk8, jdk11, cordova10)
RUN apk add --no-cache --update \
    docker docker-compose openrc doas nodejs-current npm curl python3 python3-dev py3-pip gcc musl-dev openjdk8 openjdk11 curl unzip wget
RUN python3 -m pip install --upgrade --no-cache semgrep && \
    npm install -g cordova@10
RUN rc-update add docker boot
RUN echo 'permit nopass gitlab-runner as root' > /etc/doas.d/doas.conf

# add Gradle 6.5
RUN wget -q https://services.gradle.org/distributions/gradle-6.5-all.zip -O /tmp/gradle.zip && \
    mkdir -p ${ANDROID_SDK_ROOT}/gradle && \
    unzip -qq /tmp/gradle.zip -d ${ANDROID_SDK_ROOT}/gradle && \
    mv ${ANDROID_SDK_ROOT}/gradle/* ${ANDROID_SDK_ROOT}/gradle/6.5 && \
    rm -v /tmp/gradle.zip

# add latest android command line tools
RUN wget -q https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip -O /tmp/tools.zip && \
    mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools && \
    unzip -qq /tmp/tools.zip -d ${ANDROID_SDK_ROOT}/cmdline-tools && \
    mv ${ANDROID_SDK_ROOT}/cmdline-tools/* ${ANDROID_SDK_ROOT}/cmdline-tools/latest_supported && \
    rm -v /tmp/tools.zip && \
    mkdir -p ~/.android/ && touch ~/.android/repositories.cfg

# add android platform tools, build tools 34.0.0
RUN yes | sdkmanager --sdk_root=${ANDROID_SDK_ROOT} --licenses && \
    sdkmanager --sdk_root=${ANDROID_SDK_ROOT} --install "platform-tools" "extras;google;instantapps" "build-tools;34.0.0"

# remove jdk11
RUN apk del openjdk11

# fix build tools "dx" bug
RUN mv /opt/sdk/build-tools/34.0.0/d8 /opt/sdk/build-tools/34.0.0/dx &&\
    mv /opt/sdk/build-tools/34.0.0/lib/d8.jar /opt/sdk/build-tools/34.0.0/lib/dx.jar

# set ownership of android sdk to gitlab-runner user
RUN chown gitlab-runner -R /opt/sdk

# set default jdk to jdk8
ENV JAVA_HOME "/usr/lib/jvm/java-1.8-openjdk"
ENV PATH $PATH:${JAVA_HOME}/bin

Из необычного хотелось бы отметить несколько моментов:

  • добавление библиотеки Glibc (строка 6)

  • добавление jdk8 и jdk11 (строка 52)

  • удаление jdk11 (строка 79)

  • фикс нэйминга файлов Android SDK (строка 82)

Теперь по порядку. Glibc нам понадобится, чтобы поставить все компоненты, необходимые для сборки Android-приложения, при помощи Cordova (я не стал искать сложных путей и воспользовался уже готовым решением из Github). Jdk11 нам понадобится для того, чтобы иметь возможность использовать Android command line tools, впоследствии мы его удалим, так как использовать будем Cordova 10, которая дружит с jdk8 (пожалуйста, не ругайте за легаси, да, я тоже слышал шутку Влада Тэна в подкасте, где он прерывает влажные фантазии о AI фразой в духе «Какой к черту AI, люди до сих пор 8 джавой пользуются!»). Фикс нэйминга файлов Android SDK нам понадобится для того, чтобы Gradle не падал с ошибкой на этапе сборки андроид-приложения.

Помимо вышеописанных действий мы также добавим в контейнер Nodejs, Python, Semgrep и Gradle и выполним ряд дополнительных манипуляций (в Dockerfile есть комментарии, не буду их дублировать)

Теперь у нас есть все для того, чтобы создать импровизированную версию конвейера в домашних условиях, давайте напишем docker-compose.yml

version: "3.9"

networks:
  gitlab_ce:
    driver: bridge

volumes:
  gitlab_conf:
  gitlab_data:
  gitlab_logs:
  build_runner_home:
  build_runner_conf:
  test_runner_home:
  test_runner_conf:
  deploy_runner_home:
  deploy_runner_conf:

services:
  # gitlab-ce
  gitlab-ce:
    image: gitlab/gitlab-ce:16.1.0-ce.0
    shm_size: '2gb'
    container_name: gitlab-ce
    hostname: gitlab-ce.local
    restart: always
    depends_on:
      - build-runner
      - test-runner
      - deploy-runner
    volumes:
      - gitlab_conf:/etc/gitlab
      - gitlab_data:/var/opt/gitlab
      - gitlab_logs:/var/log/gitlab
    ports:
      - "127.0.0.1:22:22"
      - "127.0.0.1:80:80"
    networks:
      - gitlab_ce
    deploy:
      resources:
        limits:
          cpus: "4"
          memory: 8G

  # gitlab-build-runner
  build-runner:
    build: ./
    container_name: gitlab-build-runner
    hostname: gitlab-build-runner.local
    restart: always
    volumes:
      - build_runner_conf:/etc/gitlab-runner
      - build_runner_home:/home/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock:rw
    networks:
      - gitlab_ce
    deploy:
      resources:
        limits:
          cpus: "4"
          memory: 4G

  # gitlab-test-runner
  test-runner:
    build: ./
    container_name: gitlab-test-runner
    hostname: gitlab-test-runner.local
    restart: always
    volumes:
      - test_runner_conf:/etc/gitlab-runner
      - test_runner_home:/home/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock:rw
    networks:
      - gitlab_ce
    deploy:
      resources:
        limits:
          cpus: "1"
          memory: 1G

  # gitlab-deploy-runner
  deploy-runner:
    build: ./
    container_name: gitlab-deploy-runner
    hostname: gitlab-deploy-runner.local
    restart: always
    volumes:
      - deploy_runner_conf:/etc/gitlab-runner
      - deploy_runner_home:/home/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock:rw
    networks:
      - gitlab_ce
    deploy:
      resources:
        limits:
          cpus: "1"
          memory: 1G

Стоит обратить внимание на секцию deploy в каждом сервисе, в ней можно указать, сколько системных ресурсов Вы хотите утилизировать под каждый сервис, также внимание стоит обратить на build: здесь указывается, из какой директории собирать образ для сервиса (где находится Dockerfile), не пропустите shm_size — это поможет заметно повысить производительность сервера Gitlab.

В данной конфигурации заложена избыточность по количеству раннеров (можно обойтись и одним, или же для каждой стадии (build, test, deploy) использовать отдельный образ, оптимизированный под определенную задачу) альтернативным методом может быть использование раннера c типом docker, однако в данном примере, несмотря на то что все раннеры являются Docker-контейнерами, я буду использовать их как shell-раннеры. Да, здесь используется импровизированный docker in docker (у сообщества есть вопросы к целесообразности использования такого метода не в последнюю очередь из-за проблем с безопасностью, но в целях эксперимента, думаю, можно попробовать и такую конфигурацию).

Теперь давайте автоматизируем процесс регистрации раннера (как вы знаете, недостаточно просто запустить раннер, его еще нужно зарегистрировать на сервере Gitlab)

#!/bin/sh

RUNNER_CONTAINER_ID=$1
RUNNER_TAG=$2
GITLAB_RUNNER_REG_TOKEN=$3

GITLAB_SUBNET=$(docker network ls | grep gitlab_ce | cut -d " " -f 4)

echo "Registering ...";

docker exec -it $RUNNER_CONTAINER_ID bash -c 'gitlab-runner register \
  --non-interactive \
  --executor "shell" \
  --docker-image alpine:latest \
  --url "http://gitlab-ce.local/" \
  --registration-token "'$GITLAB_RUNNER_REG_TOKEN'" \
  --description "docker-'$RUNNER_TAG'-runner" \
  --maintenance-note "Docker runner for gitlab-ce" \
  --tag-list "docker,'$RUNNER_TAG'" \
  --run-untagged="true" \
  --locked="false" \
  --access-level="not_protected" > /dev/null 2>&1; \
  echo "    network_mode = \"'$GITLAB_SUBNET'\"" >> /etc/gitlab-runner/config.toml'; 

echo "Done"

Данный скрипт принимает id контейнера с раннером, тэг для него и регистрационный токен. В ходе выполнения скрипта в контейнер передается команда регистрации раннера, также вносится правка в его конфигурацию, для того чтобы указать сеть, из которой ему будет доступен сервер Gitlab.

Почти все готово для запуска своего инстанса Gitlab, финальный скрипт, связывающий все в единую картину и автоматизирующий рутину.

#!/bin/sh

echo "################### Build & deploy Gitlab-CE ###################"
docker compose -p gitlab-ce up -d --build --wait gitlab-ce
echo "###############################################################"

echo "..."

echo "#################### Check Gitlab-CE state ####################"
docker compose -p gitlab-ce ps
echo "###############################################################"

echo "..."

echo "############## Gitlab runner registration token ###############"
RUNNER_REG_TOKEN=$(docker exec -it gitlab-ce gitlab-rails runner -e production 'puts Gitlab::CurrentSettings.current_application_settings.runners_registration_token')
echo "Token: $RUNNER_REG_TOKEN"
echo "###############################################################"

echo "..."

echo "################ Gitlab initial root password #################"
docker exec -it gitlab-ce bash -c 'grep 'Password:' /etc/gitlab/initial_root_password 2>/dev/null || echo "Custom root password already exists."'
echo "###############################################################"

echo "..."

echo "################# Base runners registration ###################"
echo "Registering  gitlab-build-runner ..."
./reg_new_runner.sh gitlab-build-runner build $RUNNER_REG_TOKEN
echo "Registering  gitlab-test-runner ..."
./reg_new_runner.sh gitlab-test-runner test $RUNNER_REG_TOKEN
echo "Registering  gitlab-deploy-runner ..."
./reg_new_runner.sh gitlab-deploy-runner deploy $RUNNER_REG_TOKEN
echo "###############################################################"

В итоге получаем готовый к тестам Gitlab-инстанс, который может собирать приложения и тестировать код.

зарегестрированныые раннеры
зарегестрированныые раннеры

Глава 2. Простое web-приложение

Как вы уже, наверное, догадались, здесь мы сделаем очень простое web-приложение и соберем его при помощи Webpack, на эту тему есть очень много хороших материалов, официальная документация тоже на высоте.

От себя лишь добавлю пару скриншотов из своих pet-проектов для того, чтобы показать, как организована структура файлов у меня.

файлы web-приложения выделены красным
файлы web-приложения выделены красным
содержание папки src
содержание папки src

Не буду подробно останавливаться на этом пункте, единственное, на что обращу ваше внимание, задайте в качестве директории, куда будет собираться Ваш фронтенд, папку с названием www, это упростит понимание дальнейших процессов.

конфигурация webpack
конфигурация webpack

Глава 3. Hi Cordova, pls transform my website to android app

Подведем промежуточные итоги: у нас есть простое web-приложение и Gitlab, готовый собирать наш проект и тестировать его, давайте соберем все компоненты нашего пазла воедино.

Для начала добавим конфигурационный файл config.xml для нашего приложения (я положу его в папку Cordova).

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.moviefinder.main" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
    <name>Hello-world-app</name>
    <description>My first app</description>
    <author email="username@domain.com" href="https://link-to-my.app">
        Name Surname
    </author>
    
    <preference name="android-targetSdkVersion" value="34" />
    <preference name="android-minSdkVersion" value="21" />
    
    <preference name="AndroidPersistentFileLocation" value="Compatibility" />
    
    <preference name="DisallowOverscroll" value="true" />
    
    <allow-navigation href="*" />
    <allow-intent href="*" />
    <access origin="*" />
    
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/activity">
        <activity android:exported="true"/>
    </edit-config>  

</widget>

Обратите внимание на секцию edit-config: в ней задается параметр android:exported="true" — это необходимо для того, чтобы ваше приложение было доступно на последних версиях Android.

Так как наше андроид-приложение — это по факту еще и обычный веб-сайт, добавим сборку web-приложения в Nginx-контейнере, для того чтобы мы сразу могли видеть результат нашей работы (например, если у нас нет под рукой android-эмулятора или устройства, на которое можно поставить приложение), для этого создадим Dockerfile со следующим содержанием:

FROM nginx
COPY ./www /usr/share/nginx/html

Таким образом мы получим на выходе веб-сервер с нашим web-приложением (ранее мы собирали наш web-проект в папку www)

Почти все готово, осталось только написать .gitlab-ci.yml конфигурацию для нашего пайплайна, давайте сделаем это!

stages:
  - build
  - test
  - deploy

build-code-job:
  stage: build
  tags:
    - build
    - docker
  before_script:
    - curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage?chat_id=$TELEGRAM_CHAT_ID&text=%20????%20%5B$CI_PROJECT_NAME%5D%20Build%20job%20started"
  script:
    - PATH=$PATH:/opt/sdk/gradle/6.5/bin
    - mkdir -p ~/.android/ && touch ~/.android/repositories.cfg
    - npm i
    - npm run build
    - doas docker build -t $CI_PROJECT_NAME .
    - cordova create ${CI_PROJECT_NAME}
    - cd ${CI_PROJECT_NAME}
    - rm -Rf ./www/*
    - cp -r ../www/* ./www/
    - cp ../cordova/* ./
    - cordova platform add android
    - cordova build android
  cache:
    paths:
      - node_modules
  artifacts:
    paths:
      - ./${CI_PROJECT_NAME}/platforms/android
    expire_in: 1 week
    name: ${CI_PROJECT_NAME}_${CI_JOB_ID}_android
  after_script:
    - >
      if [ $CI_JOB_STATUS == 'success' ]; then
        curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage?chat_id=$TELEGRAM_CHAT_ID&text=%20✅%20%5B$CI_PROJECT_NAME%5D%20Build%20job%20completed"
        curl -F document=@"./${CI_PROJECT_NAME}/platforms/android/app/build/outputs/apk/debug/app-debug.apk" https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument?chat_id=$TELEGRAM_CHAT_ID
      else
        curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage?chat_id=$TELEGRAM_CHAT_ID&text=%20❌%20%5B$CI_PROJECT_NAME%5D%20Build%20job%20failed%20$CI_PIPELINE_URL"
      fi

test-code-job:
  stage: test
  tags:
    - test
    - docker
  script:
    - doas docker image ls | grep "$CI_PROJECT_NAME"
    - semgrep scan src --config auto --output $CI_PROJECT_NAME-sast-report.json --json
  artifacts:
    paths:
      - $CI_PROJECT_NAME-sast-report.json
    expire_in: 4 week
    name: ${CI_PROJECT_NAME}_${CI_JOB_ID}_sast_report
  after_script:
    - >
      if [ $CI_JOB_STATUS == 'success' ]; then
        curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage?chat_id=$TELEGRAM_CHAT_ID&text=%20✅%20%5B$CI_PROJECT_NAME%5D%20All%20tests%20passed%20successfuly"
        curl -F document=@"$CI_PROJECT_NAME-sast-report.json" https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument?chat_id=$TELEGRAM_CHAT_ID
      else
        curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage?chat_id=$TELEGRAM_CHAT_ID&text=%20❌%20%5B$CI_PROJECT_NAME%5D%20Tests%20failed%20$CI_PIPELINE_URL"
      fi

deploy-code-job:
  stage: deploy
  tags:
    - deploy
    - docker
  script:
    - doas docker stop $CI_PROJECT_NAME || true && doas docker rm $CI_PROJECT_NAME || true
    - doas docker run -d --name $CI_PROJECT_NAME -p $HOST_PORT:80 --restart unless-stopped $CI_PROJECT_NAME
  after_script:
    - >
      if [ $CI_JOB_STATUS == 'success' ]; then
        curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage?chat_id=$TELEGRAM_CHAT_ID&text=%20????%20%5B$CI_PROJECT_NAME%5D%20Deploy%20job%20completed%20$PROJECT_URL"
      else
        curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage?chat_id=$TELEGRAM_CHAT_ID&text=%20❌%20%5B$CI_PROJECT_NAME%5D%20Deploy%20job%20failed%20$CI_PIPELINE_URL"
      fi

Данная конфигурация включает 3 шага:

  • build

  • test

  • deploy

Вы, конечно же, понимаете, что происходит на каждом этапе, но я поясню нюансы: помимо непосредственно сборки, тестирования и внедрения происходит также процесс информирования в Telegram-канал. Обратите внимание на условие в after_script — [ $CI_JOB_STATUS == 'success' ] — таким образом мы понимаем, выполнены ли все шаги успешно или же есть ошибки, и в зависимости от статуса конкретного этапа отправляем соответствующее сообщение.

Также обратите внимание на артефакты; на стадии сборки мы получаем в качестве артефакта папку с андроид-проектом — его потом можно открыть в Android Studio, а на стадии тестирования мы получаем отчет SAST-тестирования (вот, наконец, нам и пригодился Python и Semgrep)

Также в случае успешной сборки в Телеграм отправляется apk-файл с приложением и после прохождения тестирования SAST отчет также дублируется в мессенджер.

пример оповещений в телеграм
пример оповещений в телеграм

Полученный .apk файл можно запустить на телефоне и протестировать, а тот факт, что файл автоматически выгружается в мессенджер, поможет поделиться с вашей группой тестирования (если, конечно, она у вас есть)

И финальный штрих — определим переменные окружения для нашего проекта:

переменные окружения
переменные окружения

Теперь нам достаточно запушить изменения в репозиторий или запустить пайплайн вручную, для того чтобы конвейер заработал:

Спасибо за внимание, буду рад услышать любые советы и рекомендации от настоящих разработчиков, напоминаю: в этой области я не специалист, просто делюсь своим хобби с вами.


Небольшое отступление от темы: я веду любительский канал на youtube, где пытаюсь совершенствовать свой английский, рассказывая о своих любительских проектах, там наглядно показано,н как работает эта конфигурация Gitlab (заранее прошу прощения за свой английский, я только учусь).

Комментарии (6)


  1. karabanov
    20.07.2023 13:37

    добавление jdk8 и jdk11 (строка 52)
    удаление jdk11 (строка 79)

    Фактически из образа jdk11 не удаляется - она остаётся на том слое, где была установлена.


    1. andrewfromtver Автор
      20.07.2023 13:37

      Добрый вечер, Вы абсолютно правы, это действие необходимо скорее не для того, чтобы уменьшить размер образа - а для того, чтобы избавиться от проблем с предварительной проверкой перед сборкой андроид приложения на этапе cordova build android - дело в том, что в проекте используетс Cordova 10 и соответственно десятой версии нужна jdk8, спасибо за Ваше уточнение.


  1. NeoCode
    20.07.2023 13:37
    +2

    Вы уверены что это "для самых маленьких"? Не знаю, не знаю... но раньше, чтобы написать программу для большинства ОС, достаточно было просто поставить соответствующую среду разработки (или просто компилятор) и написать программу. Начиная с простейшего консольного hello.c под любые ОС. Под винду тоже все было просто - winapi, Delphi/Builder, MFC, WinForms, Qt, в общем практически любой фреймворк предполагал просто запуск своей среды разработки и выбор там шаблона простейшего приложения. С Android я почти не имел дела, но когда разбирался - пришел к интересным выводам: с одной стороны разработчики Android Studio попытались сделать по-человечески. Но с другой хвосты gradle и прочего скриптожопства торчат изо всех щелей, что приводит порой к странным эффектам, и даже к странным пунктам меню вроде "Sync project with gradle files", "Invalidate caches", "Reload all from disk" и даже "Repair IDE".

    И в целом, глядя на вот это всё, начинаешь понимаешь, зачем современным системам и программам десятки гигабайт оперативки.


    1. andrewfromtver Автор
      20.07.2023 13:37

      Согласен с Вами, с разработкой впринципе все на самом деле не так просто как кажется, раньше мы в целях обучения или просто, любопытства ради писали код и были счастливы от того, что все работает как и задумывалось и программа вернула ожидаемый вывод в консоль, сегодня же этим уже никого не удивишь, и чтобы заинтересовать например ребенка в школе или студента в вузе - нужно показать, как можно сделать конечный продукт, ресурсы требуются для этого конечно не маленькие, радует лишь то, что производители железа достойно держат удар и те характеристики которые раньше казались фантастическими, сегодня доступны за сравнительно небольшие деньги и простенький ноутбук с 4xCPU 8Gb RAM впринципе может купить своему ребенку почти любой родитель (тут я с ностальгией вспоминаю, как мама купила мне первый компьютер - это было достаточно давно и для нашей семьи это был значительный удар по бюджету, я очень рад за современное поколения, потому что технологии для них теперь значительно более доступны)


      1. NeoCode
        20.07.2023 13:37

        Я скорее о самих технологиях разработки. Вот все эти огромные скрипты производят впечатление чего-то неправильного. Сам способ превращения веб-приложения в андроид-приложение - тоже. Чисто с эстетической точки зрения.


        1. andrewfromtver Автор
          20.07.2023 13:37

          Безусловно полноценое приложение с большой аудиторией и сложными механиками внутри лучше изначально реализовывать на Java или Kotlin, но если Вам нужно проверить гипотезу, сделать MVP или просто если Вы хотите сэкономить время - уже имея простое web приложение на руках или, например, если стоит задача сэкономить бюджет проекта - думаю подобные инструменты трансформации web приложений в android приложения можно использовать (и многие компании такие инструменты используют). Если посмотреть с эстэтической точки зрения на этот вопрос, отбросив все внешние факторы, то здесь я с Вами полностью согласен.