From 5ed119b5dd65ea721d4917625259c9a277ac9022 Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Mon, 28 Apr 2025 16:52:00 +0300 Subject: [PATCH 1/8] feat: remove circleci, add release github action, update ci.Dockerfile --- .circleci/config.yml | 195 ------------------------- .github/workflows/release.yml | 268 +++++++++++++++++++++++++++++----- ci.Dockerfile | 21 +-- 3 files changed, 242 insertions(+), 242 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 686c0034c..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,195 +0,0 @@ -version: 2.1 -aliases: - elixir_image: &elixir_image - image: heathmont/elixir-ci:1.15.6-otp-26-alpine - auth: - username: $DOCKER_USER - password: $DOCKER_PASS - -jobs: - prelease: - docker: - - *elixir_image - environment: - MIX_ENV: prod - steps: - - checkout - - run: - name: Check variables - command: ./scripts/deploy/check-vars "in system" "ROBOT_SSH_KEY" "DOCKER_EMAIL" "DOCKER_ORG" "DOCKER_PASS" "DOCKER_USER" "HEX_API_KEY" - - run: - name: Setup robot SSH key - command: echo "$ROBOT_SSH_KEY" | base64 -d > $HOME/.ssh/id_rsa.robot && chmod 600 $HOME/.ssh/id_rsa.robot && ssh-add $HOME/.ssh/id_rsa.robot - - run: - name: Setup SSH config - command: echo -e "Host *\n IdentityFile $HOME/.ssh/id_rsa.robot\n IdentitiesOnly yes" > $HOME/.ssh/config - - restore_cache: - keys: - - v13-build_prod-{{ checksum "mix.lock" }} - - v13-build_prod- - - run: - name: Hex auth - command: mix hex.organization auth coingaming --key $HEX_API_KEY - - run: - command: mix deps.get - - run: - command: mix compile --all-warnings --warnings-as-errors - - run: - command: mix assets.clean - - run: - command: mix assets.setup - - run: - command: mix assets.deploy - - run: - command: mix release - - save_cache: - key: v13-build_prod-{{ checksum "mix.lock" }} - paths: - - deps - - _build - - ~/.mix - - save_cache: - key: v13-prod-{{ .Revision }} - paths: - - _build - - test: - docker: - - *elixir_image - environment: - MIX_ENV: test - steps: - - checkout - - run: - name: Check variables - command: ./scripts/deploy/check-vars "in system" "ROBOT_SSH_KEY" "DOCKER_EMAIL" "DOCKER_ORG" "DOCKER_PASS" "DOCKER_USER" "HEX_API_KEY" - - run: - name: Setup robot SSH key - command: echo "$ROBOT_SSH_KEY" | base64 -d > $HOME/.ssh/id_rsa.robot && chmod 600 $HOME/.ssh/id_rsa.robot && ssh-add $HOME/.ssh/id_rsa.robot - - run: - name: Setup SSH config - command: echo -e "Host *\n IdentityFile $HOME/.ssh/id_rsa.robot\n IdentitiesOnly yes" > $HOME/.ssh/config - - restore_cache: - keys: - - v13-build_test-{{ checksum "mix.lock" }} - - v13-build_test- - - run: - command: mix hex.organization auth coingaming --key $HEX_API_KEY - - run: - command: mix archive.install hex ex_env 0.3.1 --force - - run: - command: mix setup - - run: - command: mix compile --all-warnings --warnings-as-errors - - run: - command: mix format --check-formatted - - run: - command: mix credo - - run: - command: mix test - - save_cache: - key: v13-build_test-{{ checksum "mix.lock" }} - paths: - - deps - - _build - - ~/.mix - dockerhub: - docker: - - *elixir_image - steps: - - checkout - - setup_remote_docker: - docker_layer_caching: true - - attach_workspace: - at: ./ - - restore_cache: - keys: - - v13-prod-{{ .Revision }} - - v13-prod- - - run: - name: Docker login - command: docker login -u $DOCKER_USER -p $DOCKER_PASS - - run: scripts/deploy/docker-build-ci push $CIRCLE_TAG - deploy: - docker: - - *elixir_image - steps: - - checkout - - setup_remote_docker: - docker_layer_caching: true - - attach_workspace: - at: ./ - - run: - name: Setup robot SSH key - command: | - echo "$ROBOT_SSH_KEY" | base64 -d > $HOME/.ssh/id_rsa.robot && chmod 600 $HOME/.ssh/id_rsa.robot && ssh-add $HOME/.ssh/id_rsa.robot - echo -e "Host *\n IdentityFile $HOME/.ssh/id_rsa.robot\n IdentitiesOnly yes" > $HOME/.ssh/config - - run: - name: Setup deploy tool auth - command: echo "{\"user\":\"$DEPLOY_USER\", \"pass\":\"$DEPLOY_PASS\"}" > $HOME/.deploy_auth - - run: - name: Deploy - command: scripts/deploy/stacks-deploy $CIRCLE_TAG - semrelease: - docker: - - *elixir_image - environment: - MIX_ENV: test - resource_class: xlarge - steps: - - checkout - - restore_cache: - keys: - - v13-node_modules-{{ checksum "package-lock.json" }} - - v13-node_modules- - - restore_cache: - keys: - - v13-build_test-{{ checksum "mix.lock" }} - - v13-build_test- - - run: - name: Hex auth - command: mix hex.organization auth coingaming --key $HEX_API_KEY - - run: - name: Semantic Release - command: mix semantic.release - - save_cache: - key: v13-node_modules-{{ checksum "package-lock.json" }} - paths: - - node_modules - - -workflows: - version: 2 - workflow: - jobs: - - prelease: - context: global - - test: - context: global - - semrelease: - context: global - filters: - branches: - only: - - main - requires: - - test - - dockerhub: - context: global - filters: - branches: - only: - - main - requires: - - prelease - - deploy: - context: global - filters: - branches: - only: - - main - tags: - only: /^v.*/ - requires: - - dockerhub - \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6cfe7ec92..ef10e4ca5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,49 +1,243 @@ -name: build +name: Publish Docker Image and Bundles on: push: - branches: - - main + tags: ['v*'] + branches: [main] + pull_request: + branches: [main] + release: + types: [created] jobs: - tag-release: - runs-on: ubuntu-latest - outputs: - release-version: ${{ steps.release-version.outputs.version }} + prelease: + runs-on: ubuntu-22.04 + env: + DOCKER_USER: ${{ secrets.DOCKER_USER }} + DOCKER_PASS: ${{ secrets.DOCKER_PASS }} + MIX_ENV: prod steps: - - name: Checkout + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Checkout code uses: actions/checkout@v4 - # Tag new release - - name: Set up Node.js + - name: Authenticate with Docker + run: echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin + + - name: Run container + run: | + docker run --detach \ + --name elixir_ci \ + --volume ${{ github.workspace }}:/workspace \ + --workdir /workspace \ + heathmont/elixir-ci:1.18.1-otp-27-alpine + + - name: Execute inside container + run: docker exec elixir_ci mix deps.get + - name: Check variables + run: ./scripts/deploy/check-vars "in system" "ROBOT_SSH_KEY" "DOCKER_EMAIL" "DOCKER_ORG" "DOCKER_PASS" "DOCKER_USER" "HEX_API_KEY" + + - name: Setup SSH key + run: | + mkdir -p ~/.ssh + echo "${{ secrets.ROBOT_SSH_KEY }}" | base64 -d > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H github.com >> ~/.ssh/known_hosts + echo -e "Host *\n IdentityFile ~/.ssh/id_rsa\n IdentitiesOnly yes" > ~/.ssh/config + shell: bash + + - name: Restore dependencies cache + uses: actions/cache@v3 + with: + path: | + deps + _build + ~/.mix + key: v13-build_prod-${{ hashFiles('mix.lock') }} + restore-keys: | + v13-build_prod- + + - name: Authenticate with Hex + run: mix hex.organization auth coingaming --key "${{ secrets.HEX_API_KEY }}" + + - name: Install dependencies + run: mix deps.get + + - name: Compile project + run: mix compile --all-warnings --warnings-as-errors + + - name: Setup assets + run: | + mix assets.clean + mix assets.setup + mix assets.deploy + + - name: Build release + run: mix release + + - name: Restore build cache + uses: actions/cache@v3 + with: + path: _build + key: v13-prod-${{ github.sha }} + restore-keys: | + v13-prod- + + test: + runs-on: ubuntu-22.04 + env: + MIX_ENV: test + steps: + - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 14 + node-version: 20 + - name: Checkout code + uses: actions/checkout@v4 + + - name: Authenticate with Docker + run: echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin - - name: Install Semantic Release, plugins and preset - working-directory: . + - name: Run container run: | - npm install -g \ - semantic-release@18.0.0 \ - conventional-changelog-conventionalcommits@4.6.1 - - # - name: Run Sematic Release - # working-directory: . - # env: - # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # run: semantic-release --branches main - - # # Get new release version - # - name: Get release tag - # id: release-tag - # uses: WyriHaximus/github-action-get-previous-tag@v1.1 - - # - name: Get release version - # id: release-version - # uses: actions/github-script@v6 - # with: - # script: | - # core.setOutput( - # 'version', - # '${{ steps.release-tag.outputs.tag }}'.slice(1) - # ) + docker run --detach \ + --name elixir_ci \ + --volume ${{ github.workspace }}:/workspace \ + --workdir /workspace \ + heathmont/elixir-ci:1.18.1-otp-27-alpine + + - name: Execute inside container + run: docker exec elixir_ci mix deps.get + - name: Check variables + run: ./scripts/deploy/check-vars "in system" "ROBOT_SSH_KEY" "DOCKER_EMAIL" "DOCKER_ORG" "DOCKER_PASS" "DOCKER_USER" "HEX_API_KEY" + + - name: Restore dependencies cache + uses: actions/cache@v3 + with: + path: | + deps + _build + ~/.mix + key: v13-build_test-{{ checksum "mix.lock" }} + restore-keys: | + v13-build_test- + + - name: Authenticate with Hex + run: mix hex.organization auth coingaming --key "${{ secrets.HEX_API_KEY }}" + + - name: Install dependencies + run: mix deps.get + + - name: Compile project + run: mix compile --all-warnings --warnings-as-errors + + - name: Check code formatting + run: mix format --check-formatted + + - name: Run Credo (Linting) + run: mix credo + + - name: Run tests + run: mix test + + - name: Save test build cache + uses: actions/cache@v3 + with: + path: | + deps + _build + ~/.mix + key: v13-build_test-${{ hashFiles('mix.lock') }} + restore-keys: | + v13-build_test- + + dockerhub: + runs-on: ubuntu-22.04 + needs: prelease + if: github.ref == 'refs/heads/main' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Log in to DockerHub + run: echo "${{ secrets.DOCKER_PASS }}" | docker login -u "${{ secrets.DOCKER_USER }}" --password-stdin + + - name: Restore build cache + uses: actions/cache@v3 + with: + path: _build + key: v13-prod-${{ github.sha }} + restore-keys: | + v13-prod- + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push Docker image + run: scripts/deploy/docker-build-ci push $GITHUB_REF_NAME + + + deploy: + runs-on: ubuntu-22.04 + needs: dockerhub + if: startsWith(github.ref, 'refs/heads/main') || startsWith(github.ref, 'refs/tags/v') + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up SSH key + run: | + echo "${{ secrets.ROBOT_SSH_KEY }}" | base64 -d > $HOME/.ssh/id_rsa.robot + chmod 600 $HOME/.ssh/id_rsa.robot + ssh-add $HOME/.ssh/id_rsa.robot + echo -e "Host *\n IdentityFile $HOME/.ssh/id_rsa.robot\n IdentitiesOnly yes" > $HOME/.ssh/config + + - name: Set up deploy tool auth + run: echo "{\"user\":\"${{ secrets.DEPLOY_USER }}\", \"pass\":\"${{ secrets.DEPLOY_PASS }}\"}" > $HOME/.deploy_auth + + - name: Deploy + run: scripts/deploy/stacks-deploy $GITHUB_REF_NAME + + semrelease: + runs-on: ubuntu-22.04 + needs: test + if: github.ref == 'refs/heads/main' + env: + MIX_ENV: test + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Restore node_modules cache + uses: actions/cache@v4 + with: + path: node_modules + key: v13-node_modules-${{ hashFiles('package-lock.json') }} + restore-keys: | + v13-node_modules- + + - name: Restore Elixir build cache + uses: actions/cache@v4 + with: + path: | + deps + _build + ~/.mix + key: v13-build_test-${{ hashFiles('mix.lock') }} + restore-keys: | + v13-build_test- + + - name: Hex auth + run: mix hex.organization auth coingaming --key "${{ secrets.HEX_API_KEY }}" + + - name: Run Semantic Release + run: mix semantic.release + + - name: Save node_modules cache + uses: actions/cache@v4 + with: + path: node_modules + key: v13-node_modules-${{ hashFiles('package-lock.json') }} \ No newline at end of file diff --git a/ci.Dockerfile b/ci.Dockerfile index dc1aba547..59d2ca550 100644 --- a/ci.Dockerfile +++ b/ci.Dockerfile @@ -1,14 +1,15 @@ -FROM alpine:3.18.2 -RUN apk upgrade --no-cache && apk add --no-cache postgresql-client bash openssl libgcc libstdc++ ncurses-libs bash libcrypto1.1 +FROM alpine:3.18.2@sha256:bd649691cf299c58fec56fb84a5067a915da6915897c6f846a6e317e5ff42a4d -ARG APP_NAME -ARG MIX_ENV - -ENV REPLACE_OS_VARS=true \ - MIX_ENV=${MIX_ENV} \ - APP_NAME=${APP_NAME} +RUN apk upgrade --no-cache && \ + apk add --no-cache postgresql-client=15.3-r0 openssl=3.1.2-r0 libgcc=12.2.1_git20220924-r10 libstdc++=12.2.1_git20220924-r10 ncurses-libs=6.4_p20230506-r0 tini +RUN addgroup -S appgroup && adduser -S appuser -G appgroup +USER appuser WORKDIR /opt/app -COPY _build ./_build -CMD _build/prod/rel/moon/bin/moon start +COPY --chown=appuser:appgroup _build ./_build + +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:4000/health || exit 1 + +CMD ["tini", "--", "_build/prod/rel/moon/bin/moon", "start"] \ No newline at end of file From 277ea010e54d8577e5f3b77ebfb6b3521201ac30 Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Tue, 29 Apr 2025 14:29:54 +0300 Subject: [PATCH 2/8] fix: remove circle ci from ci build --- .github/workflows/release.yml | 11 ++++++----- scripts/deploy/docker-build-ci | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef10e4ca5..b3e313877 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -121,10 +121,8 @@ jobs: deps _build ~/.mix - key: v13-build_test-{{ checksum "mix.lock" }} - restore-keys: | - v13-build_test- - + key: v13-build_test-${{ hashFiles('mix.lock') }} + - name: Authenticate with Hex run: mix hex.organization auth coingaming --key "${{ secrets.HEX_API_KEY }}" @@ -196,7 +194,9 @@ jobs: echo -e "Host *\n IdentityFile $HOME/.ssh/id_rsa.robot\n IdentitiesOnly yes" > $HOME/.ssh/config - name: Set up deploy tool auth - run: echo "{\"user\":\"${{ secrets.DEPLOY_USER }}\", \"pass\":\"${{ secrets.DEPLOY_PASS }}\"}" > $HOME/.deploy_auth + run: | + echo "{\"user\":\"${{ secrets.DEPLOY_USER }}\", \"pass\":\"${{ secrets.DEPLOY_PASS }}\"}" > $HOME/.deploy_auth + chmod 600 $HOME/.deploy_auth - name: Deploy run: scripts/deploy/stacks-deploy $GITHUB_REF_NAME @@ -217,6 +217,7 @@ jobs: path: node_modules key: v13-node_modules-${{ hashFiles('package-lock.json') }} restore-keys: | + v13-node_modules-${{ github.ref }} v13-node_modules- - name: Restore Elixir build cache diff --git a/scripts/deploy/docker-build-ci b/scripts/deploy/docker-build-ci index 268543987..5e8635e30 100755 --- a/scripts/deploy/docker-build-ci +++ b/scripts/deploy/docker-build-ci @@ -13,8 +13,8 @@ function usage { echo "Examples:" echo "" echo " docker-build - Build the current git commit" - echo " docker-build push \$CIRCLE_TAG - Push and build the image in CI" - exit + echo " docker-build push - Push and build the image with the specified version" + exit } if [ "$1" = "help" ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then From 7b2d7d7d3872181148be20124c7b95f03ecbfb36 Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Wed, 30 Apr 2025 15:21:35 +0300 Subject: [PATCH 3/8] fix: update scripts --- .github/actions/setup_elixir/action.yml | 25 +++ .github/workflows/build-and-test.yml | 42 ++++ .github/workflows/release.yml | 245 ++++-------------------- Dockerfile | 56 ++++++ ci.Dockerfile | 15 -- scripts/deploy/docker-build | 45 +++-- scripts/deploy/docker-build-ci | 45 ----- 7 files changed, 188 insertions(+), 285 deletions(-) create mode 100644 .github/actions/setup_elixir/action.yml create mode 100644 .github/workflows/build-and-test.yml create mode 100644 Dockerfile delete mode 100644 ci.Dockerfile delete mode 100755 scripts/deploy/docker-build-ci diff --git a/.github/actions/setup_elixir/action.yml b/.github/actions/setup_elixir/action.yml new file mode 100644 index 000000000..4ee2533e5 --- /dev/null +++ b/.github/actions/setup_elixir/action.yml @@ -0,0 +1,25 @@ +name: Setup Elixir App + +runs: + using: "composite" + steps: + - uses: erlef/setup-elixir@v1 + with: + elixir-version: '1.15' + otp-version: '26' + + - uses: actions/cache@v4 + with: + path: deps + key: ${{ runner.os }}-deps-${{ hashFiles('**/mix.lock') }} + + - uses: actions/cache@v4 + with: + path: _build + key: ${{ runner.os }}-build-${{ github.sha }} + + - run: mix deps.get + shell: bash + + - run: mix compile --warnings-as-errors + shell: bash \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 000000000..83d8563c4 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,42 @@ +name: Build and Test + +on: + push: + branches: + - main + pull_request: + +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Elixir + uses: ./.github/actions/setup_elixir + + - name: Run tests + run: mix test + + - name: Read VERSION file and create tag + if: github.ref == 'refs/heads/main' && success() + run: | + TAG="v$(cat VERSION | tr -d '[:space:]')" + echo "Using tag: $TAG" + + git config user.name "github-actions" + git config user.email "github-actions@github.com" + + git fetch --tags + + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "Tag $TAG already exists. Skipping." + else + git tag "$TAG" + git push origin "$TAG" + echo "Tag $TAG pushed." + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3e313877..63c4ce83d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,244 +1,71 @@ -name: Publish Docker Image and Bundles +name: Release Docker Image on: push: - tags: ['v*'] - branches: [main] - pull_request: - branches: [main] - release: - types: [created] + tags: + - 'v*' jobs: - prelease: - runs-on: ubuntu-22.04 - env: - DOCKER_USER: ${{ secrets.DOCKER_USER }} - DOCKER_PASS: ${{ secrets.DOCKER_PASS }} - MIX_ENV: prod - steps: - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - - name: Checkout code - uses: actions/checkout@v4 - - - name: Authenticate with Docker - run: echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin - - - name: Run container - run: | - docker run --detach \ - --name elixir_ci \ - --volume ${{ github.workspace }}:/workspace \ - --workdir /workspace \ - heathmont/elixir-ci:1.18.1-otp-27-alpine - - - name: Execute inside container - run: docker exec elixir_ci mix deps.get - - name: Check variables - run: ./scripts/deploy/check-vars "in system" "ROBOT_SSH_KEY" "DOCKER_EMAIL" "DOCKER_ORG" "DOCKER_PASS" "DOCKER_USER" "HEX_API_KEY" - - - name: Setup SSH key - run: | - mkdir -p ~/.ssh - echo "${{ secrets.ROBOT_SSH_KEY }}" | base64 -d > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan -H github.com >> ~/.ssh/known_hosts - echo -e "Host *\n IdentityFile ~/.ssh/id_rsa\n IdentitiesOnly yes" > ~/.ssh/config - shell: bash - - - name: Restore dependencies cache - uses: actions/cache@v3 - with: - path: | - deps - _build - ~/.mix - key: v13-build_prod-${{ hashFiles('mix.lock') }} - restore-keys: | - v13-build_prod- - - - name: Authenticate with Hex - run: mix hex.organization auth coingaming --key "${{ secrets.HEX_API_KEY }}" - - - name: Install dependencies - run: mix deps.get - - - name: Compile project - run: mix compile --all-warnings --warnings-as-errors - - - name: Setup assets - run: | - mix assets.clean - mix assets.setup - mix assets.deploy - - - name: Build release - run: mix release - - - name: Restore build cache - uses: actions/cache@v3 - with: - path: _build - key: v13-prod-${{ github.sha }} - restore-keys: | - v13-prod- - - test: - runs-on: ubuntu-22.04 - env: - MIX_ENV: test - steps: - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - - name: Checkout code - uses: actions/checkout@v4 - - - name: Authenticate with Docker - run: echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin - - - name: Run container - run: | - docker run --detach \ - --name elixir_ci \ - --volume ${{ github.workspace }}:/workspace \ - --workdir /workspace \ - heathmont/elixir-ci:1.18.1-otp-27-alpine - - - name: Execute inside container - run: docker exec elixir_ci mix deps.get - - name: Check variables - run: ./scripts/deploy/check-vars "in system" "ROBOT_SSH_KEY" "DOCKER_EMAIL" "DOCKER_ORG" "DOCKER_PASS" "DOCKER_USER" "HEX_API_KEY" - - - name: Restore dependencies cache - uses: actions/cache@v3 - with: - path: | - deps - _build - ~/.mix - key: v13-build_test-${{ hashFiles('mix.lock') }} - - - name: Authenticate with Hex - run: mix hex.organization auth coingaming --key "${{ secrets.HEX_API_KEY }}" - - - name: Install dependencies - run: mix deps.get - - - name: Compile project - run: mix compile --all-warnings --warnings-as-errors - - - name: Check code formatting - run: mix format --check-formatted - - - name: Run Credo (Linting) - run: mix credo - - - name: Run tests - run: mix test - - - name: Save test build cache - uses: actions/cache@v3 - with: - path: | - deps - _build - ~/.mix - key: v13-build_test-${{ hashFiles('mix.lock') }} - restore-keys: | - v13-build_test- + release: + name: Build, Push Docker Image, and Deploy + runs-on: ubuntu-latest - dockerhub: - runs-on: ubuntu-22.04 - needs: prelease - if: github.ref == 'refs/heads/main' steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Log in to DockerHub - run: echo "${{ secrets.DOCKER_PASS }}" | docker login -u "${{ secrets.DOCKER_USER }}" --password-stdin + - uses: actions/checkout@v4 - - name: Restore build cache - uses: actions/cache@v3 + - name: Log in to Docker Hub + uses: docker/login-action@v3 with: - path: _build - key: v13-prod-${{ github.sha }} - restore-keys: | - v13-prod- - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and push Docker image - run: scripts/deploy/docker-build-ci push $GITHUB_REF_NAME - - - deploy: - runs-on: ubuntu-22.04 - needs: dockerhub - if: startsWith(github.ref, 'refs/heads/main') || startsWith(github.ref, 'refs/tags/v') - steps: - - name: Checkout code - uses: actions/checkout@v4 + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASS }} + + - name: Build and push docker image + env: + MIX_ENV: prod + APP_NAME: moon + SERVICE_NAME: moon + DOCKER_ORG: ${{ secrets.DOCKER_USER }} + APP_VSN: ${{ github.ref_name }} + run: | + ./scripts/docker_build.sh push $APP_VSN - - name: Set up SSH key + - name: Setup robot SSH key run: | - echo "${{ secrets.ROBOT_SSH_KEY }}" | base64 -d > $HOME/.ssh/id_rsa.robot + echo "$ROBOT_SSH_KEY" | base64 -d > $HOME/.ssh/id_rsa.robot chmod 600 $HOME/.ssh/id_rsa.robot - ssh-add $HOME/.ssh/id_rsa.robot echo -e "Host *\n IdentityFile $HOME/.ssh/id_rsa.robot\n IdentitiesOnly yes" > $HOME/.ssh/config + eval "$(ssh-agent -s)" && ssh-add $HOME/.ssh/id_rsa.robot - - name: Set up deploy tool auth - run: | - echo "{\"user\":\"${{ secrets.DEPLOY_USER }}\", \"pass\":\"${{ secrets.DEPLOY_PASS }}\"}" > $HOME/.deploy_auth - chmod 600 $HOME/.deploy_auth + - name: Setup deploy tool auth + run: echo "{\"user\":\"$DEPLOY_USER\", \"pass\":\"$DEPLOY_PASS\"}" > $HOME/.deploy_auth - name: Deploy - run: scripts/deploy/stacks-deploy $GITHUB_REF_NAME - - semrelease: - runs-on: ubuntu-22.04 - needs: test - if: github.ref == 'refs/heads/main' - env: - MIX_ENV: test - steps: - - name: Checkout code - uses: actions/checkout@v4 + run: ./scripts/deploy/stacks-deploy ${{ github.ref_name }} - name: Restore node_modules cache - uses: actions/cache@v4 + uses: actions/cache@v3 with: path: node_modules key: v13-node_modules-${{ hashFiles('package-lock.json') }} restore-keys: | - v13-node_modules-${{ github.ref }} v13-node_modules- - - name: Restore Elixir build cache - uses: actions/cache@v4 + - name: Restore mix.lock cache + uses: actions/cache@v3 with: - path: | - deps - _build - ~/.mix + path: _build key: v13-build_test-${{ hashFiles('mix.lock') }} restore-keys: | v13-build_test- - name: Hex auth - run: mix hex.organization auth coingaming --key "${{ secrets.HEX_API_KEY }}" - - - name: Run Semantic Release + run: mix hex.organization auth coingaming --key $HEX_API_KEY + + - name: Semantic Release run: mix semantic.release - name: Save node_modules cache - uses: actions/cache@v4 + uses: actions/cache@v3 with: path: node_modules - key: v13-node_modules-${{ hashFiles('package-lock.json') }} \ No newline at end of file + key: v13-node_modules-${{ hashFiles('package-lock.json') }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..7be760743 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,56 @@ +# ---- Build stage ---- +FROM heathmont/elixir-ci:1.15.6-otp-26-alpine AS build + +ARG MIX_ENV=prod +ARG APP_NAME=moon +ARG APP_VSN + +ENV MIX_ENV=${MIX_ENV} \ + APP_NAME=${APP_NAME} \ + APP_VSN=${APP_VSN} + +WORKDIR /app + +RUN apk add --no-cache \ + openssh \ + inotify-tools + +COPY mix.exs mix.lock ./ +COPY config config + +RUN curl -fsSL https://s3.amazonaws.com/rebar3/rebar3 -o /usr/local/bin/rebar3 && \ + chmod +x /usr/local/bin/rebar3 && \ + mix local.hex --force && \ + mix local.rebar --force && \ + mix deps.get --only ${MIX_ENV} + +COPY . . + +RUN mix deps.compile && \ + npm install --prefix ./assets && \ + npm run deploy --prefix ./assets && \ + mix phx.digest && \ + mix release + +# ---- Runtime stage ---- +FROM alpine:3.18.2 AS app + +RUN apk upgrade --no-cache && \ + apk add --no-cache \ + erlang-dev \ + perl \ + postgresql-client \ + openssl \ + ncurses-libs \ + tini + +RUN addgroup -S appgroup && adduser -S appuser -G appgroup +USER appuser +WORKDIR /opt/app + +COPY _build ./_build + +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:4000/health || exit 1 + +CMD ["tini", "--", "./bin/moon", "start"] \ No newline at end of file diff --git a/ci.Dockerfile b/ci.Dockerfile deleted file mode 100644 index 59d2ca550..000000000 --- a/ci.Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM alpine:3.18.2@sha256:bd649691cf299c58fec56fb84a5067a915da6915897c6f846a6e317e5ff42a4d - -RUN apk upgrade --no-cache && \ - apk add --no-cache postgresql-client=15.3-r0 openssl=3.1.2-r0 libgcc=12.2.1_git20220924-r10 libstdc++=12.2.1_git20220924-r10 ncurses-libs=6.4_p20230506-r0 tini - -RUN addgroup -S appgroup && adduser -S appuser -G appgroup -USER appuser -WORKDIR /opt/app - -COPY --chown=appuser:appgroup _build ./_build - -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:4000/health || exit 1 - -CMD ["tini", "--", "_build/prod/rel/moon/bin/moon", "start"] \ No newline at end of file diff --git a/scripts/deploy/docker-build b/scripts/deploy/docker-build index 533ebd1bd..0857403bf 100755 --- a/scripts/deploy/docker-build +++ b/scripts/deploy/docker-build @@ -3,38 +3,51 @@ source "$(dirname "$0")/vars" function usage { - echo "docker-build is a tool to build elixir project docker image." + echo "docker-build is a tool to build and optionally push the Elixir app Docker image." echo "" - echo "Usage: docker-build" + echo "Usage: ./docker_build.sh [push] [version]" + echo "" + echo "push: Push the image after successful build." + echo "version: Optional version tag (e.g., v1.2.3)." + echo "" + echo "Examples:" + echo " ./docker_build.sh - Build the image with current git hash" + echo " ./docker_build.sh push v1.2.3 - Build and push with tag v1.2.3" + exit } -if [ "$1" = "help" ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then +if [[ "$1" == "help" || "$1" == "--help" || "$1" == "-h" ]]; then usage fi set -e -BUILD=`git rev-parse --short HEAD` +BUILD_SHA=$(git rev-parse --short HEAD) TAG="$2" +BASE_TAG="${DOCKER_ORG}/${SERVICE_NAME}" + +# Назначаем теги +IMAGE_TAG="${BASE_TAG}:v${APP_VSN}-${BUILD_SHA}" +LATEST_TAG="${BASE_TAG}:latest" if [ "$TAG" = "v${APP_VSN}" ]; then - VERSION_TAG="${DOCKER_ORG}/${SERVICE_NAME}:v${APP_VSN}" - VERSION_TAG_BUILD="-t ${VERSION_TAG}" + VERSION_TAG="${BASE_TAG}:${TAG}" fi +echo "🔨 Building image..." docker build \ - --build-arg MIX_ENV=$MIX_ENV \ - --build-arg APP_NAME=$APP_NAME \ - --build-arg SERVICE_NAME=$SERVICE_NAME \ - --build-arg APP_VSN=$APP_VSN \ - --build-arg GITHUB_SSH_KEY="$GITHUB_SSH_KEY" \ - --build-arg HEX_API_KEY="$HEX_API_KEY" \ - -t ${DOCKER_ORG}/${SERVICE_NAME}:v${APP_VSN}-${BUILD} \ - $VERSION_TAG_BUILD \ - -t ${DOCKER_ORG}/${SERVICE_NAME}:latest . + --build-arg MIX_ENV=$MIX_ENV \ + --build-arg APP_NAME=$APP_NAME \ + -t $IMAGE_TAG \ + -t $LATEST_TAG \ + ${VERSION_TAG:+-t $VERSION_TAG} . + +echo "✅ Built: $IMAGE_TAG" if [ "$1" = "push" ]; then - docker push ${DOCKER_ORG}/${SERVICE_NAME}:v${APP_VSN}-${BUILD} + echo "🚀 Pushing..." + docker push $IMAGE_TAG + docker push $LATEST_TAG if [ -n "$VERSION_TAG" ]; then docker push $VERSION_TAG fi diff --git a/scripts/deploy/docker-build-ci b/scripts/deploy/docker-build-ci deleted file mode 100755 index 5e8635e30..000000000 --- a/scripts/deploy/docker-build-ci +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash - -source "$(dirname "$0")/vars" - -function usage { - echo "docker-build is a tool to build elixir project docker image." - echo "" - echo "Usage: docker-build [push] [version]" - echo "" - echo "push: Also push the image after successful build." - echo "version: Exact version to build and push. Usuful for CI. Defaults to current git commit." - echo "" - echo "Examples:" - echo "" - echo " docker-build - Build the current git commit" - echo " docker-build push - Push and build the image with the specified version" - exit -} - -if [ "$1" = "help" ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then - usage -fi - -set -e - -BUILD=`git rev-parse --short HEAD` -TAG="$2" - -if [ "$TAG" = "v${APP_VSN}" ]; then - VERSION_TAG="${DOCKER_ORG}/${SERVICE_NAME}:v${APP_VSN}" -fi - -docker build \ - --build-arg MIX_ENV=$MIX_ENV \ - --build-arg APP_NAME=$APP_NAME \ - --build-arg SERVICE_NAME=$SERVICE_NAME \ - -t ${DOCKER_ORG}/${SERVICE_NAME}:v${APP_VSN} \ - --file ci.Dockerfile . - -if [ "$1" = "push" ]; then - docker push ${DOCKER_ORG}/${SERVICE_NAME}:v${APP_VSN} - if [ -n "$VERSION_TAG" ]; then - docker push $VERSION_TAG - fi -fi From 3b21b5de34cac58b8ff06b9330cf6e124252690e Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Wed, 30 Apr 2025 15:47:41 +0300 Subject: [PATCH 4/8] fix: add env var for semantic release --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 63c4ce83d..d4ec2f861 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,6 +62,8 @@ jobs: run: mix hex.organization auth coingaming --key $HEX_API_KEY - name: Semantic Release + env: + MIX_ENV: test run: mix semantic.release - name: Save node_modules cache From 657e2fae46e1b1aefaf73fe5998bc3fe6136ca74 Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Mon, 26 May 2025 17:00:25 +0300 Subject: [PATCH 5/8] fix/add EOF --- .github/actions/setup_elixir/action.yml | 3 ++- Dockerfile | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup_elixir/action.yml b/.github/actions/setup_elixir/action.yml index 4ee2533e5..f4cd709da 100644 --- a/.github/actions/setup_elixir/action.yml +++ b/.github/actions/setup_elixir/action.yml @@ -22,4 +22,5 @@ runs: shell: bash - run: mix compile --warnings-as-errors - shell: bash \ No newline at end of file + shell: bash + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 7be760743..106b50733 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,4 +53,4 @@ COPY _build ./_build HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:4000/health || exit 1 -CMD ["tini", "--", "./bin/moon", "start"] \ No newline at end of file +CMD ["tini", "--", "./bin/moon", "start"] From 03ce193625b92c42b26bbbad4638c88c01f7e149 Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Tue, 3 Jun 2025 09:52:10 +0300 Subject: [PATCH 6/8] fix: improve scripts --- .github/workflows/release.yml | 2 +- Dockerfile | 1 + scripts/deploy/docker-build | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4ec2f861..4f2dbc167 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: DOCKER_ORG: ${{ secrets.DOCKER_USER }} APP_VSN: ${{ github.ref_name }} run: | - ./scripts/docker_build.sh push $APP_VSN + scripts/deploy/docker-build push $APP_VSN - name: Setup robot SSH key run: | diff --git a/Dockerfile b/Dockerfile index 106b50733..2f1439e3e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,6 +47,7 @@ RUN apk upgrade --no-cache && \ RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser WORKDIR /opt/app +EXPOSE 4000 COPY _build ./_build diff --git a/scripts/deploy/docker-build b/scripts/deploy/docker-build index 0857403bf..24c9047a5 100755 --- a/scripts/deploy/docker-build +++ b/scripts/deploy/docker-build @@ -26,7 +26,6 @@ BUILD_SHA=$(git rev-parse --short HEAD) TAG="$2" BASE_TAG="${DOCKER_ORG}/${SERVICE_NAME}" -# Назначаем теги IMAGE_TAG="${BASE_TAG}:v${APP_VSN}-${BUILD_SHA}" LATEST_TAG="${BASE_TAG}:latest" From 38c9fd8724b6d5c913b0ba30571643ba3323e0a0 Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Tue, 3 Jun 2025 10:52:05 +0300 Subject: [PATCH 7/8] fix: improve scripts --- scripts/deploy/docker-build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/deploy/docker-build b/scripts/deploy/docker-build index 24c9047a5..21a38f46e 100755 --- a/scripts/deploy/docker-build +++ b/scripts/deploy/docker-build @@ -5,14 +5,14 @@ source "$(dirname "$0")/vars" function usage { echo "docker-build is a tool to build and optionally push the Elixir app Docker image." echo "" - echo "Usage: ./docker_build.sh [push] [version]" + echo "Usage: ./docker_build [push] [version]" echo "" echo "push: Push the image after successful build." echo "version: Optional version tag (e.g., v1.2.3)." echo "" echo "Examples:" - echo " ./docker_build.sh - Build the image with current git hash" - echo " ./docker_build.sh push v1.2.3 - Build and push with tag v1.2.3" + echo " ./docker_build - Build the image with current git hash" + echo " ./docker_build push v1.2.3 - Build and push with tag v1.2.3" exit } From 38a681a39572bfdbf62c96462be532529d178140 Mon Sep 17 00:00:00 2001 From: Nadezda Barinova Date: Tue, 3 Jun 2025 12:56:19 +0300 Subject: [PATCH 8/8] fix: EOF has been added --- .github/actions/setup_elixir/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup_elixir/action.yml b/.github/actions/setup_elixir/action.yml index f4cd709da..9125c294e 100644 --- a/.github/actions/setup_elixir/action.yml +++ b/.github/actions/setup_elixir/action.yml @@ -23,4 +23,5 @@ runs: - run: mix compile --warnings-as-errors shell: bash + \ No newline at end of file