diff --git a/README.md b/README.md index ed98c24..f2739c7 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,6 @@ A collection of GitHub Actions workflows to work with Kamal 2 ├── 01.deploy_production.yaml # deploy to production on push to branch ├── 02.deploy_manually.yaml # deploy to selected envrironment on manual trigger ├── 03.kamal_run_command.yaml # run Kamal command on selected environment - ├── kamal-deploy - │   └── action.yaml └── setup └── action.yml └──.kamal @@ -31,8 +29,24 @@ A collection of GitHub Actions workflows to work with Kamal 2 ├── 01.deploy_production.yaml # deploy to production on push to branch ├── 02.deploy_manually.yaml # deploy to selected envrironment on manual trigger ├── 03.kamal_run_command.yaml # run Kamal command on selected environment - ├── kamal-deploy - │   └── action.yaml + └── setup + └── action.yml + └──.kamal + └── secrets-common + └── config + ├── deploy.production.yml # production environment configuration + └── deploy.yml # commom configuration +``` + +## GCP + +```bash +└── gcp + └──.github + └── workflows + ├── 01.deploy_production.yaml # deploy to production on push to branch + ├── 02.deploy_manually.yaml # deploy to selected envrironment on manual trigger + ├── 03.kamal_run_command.yaml # run Kamal command on selected environment └── setup └── action.yml └──.kamal diff --git a/gcp/.github/workflows/01.deploy_production.yaml b/gcp/.github/workflows/01.deploy_production.yaml new file mode 100644 index 0000000..086c896 --- /dev/null +++ b/gcp/.github/workflows/01.deploy_production.yaml @@ -0,0 +1,46 @@ +name: 01. Deploy to Production + +permissions: + id-token: write + contents: read + +on: + workflow_dispatch: + push: + branches: + - master + +jobs: + build_and_deploy: + name: deploy-production + concurrency: + group: production_environment + cancel-in-progress: true + environment: + name: production + url: https://jetrockets.com + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_branch }} + + - name: Setup + uses: ./.github/workflows/setup + id: setup + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + gcp_credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' + gcp_registry_username: '' + + - name: Kamal Deploy + uses: igor-alexandrov/kamal-deploy@v0.1.3 + with: + registry-username: '' + registry-password: ${{ steps.setup.outputs.kamal-registry-password }} + environment: production + env: + DATABASE_URL: ${{ secrets.DATABASE_URL }} + REDIS_URL: ${{ secrets.REDIS_URL }} + RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} diff --git a/gcp/.github/workflows/02.deploy_manually.yaml b/gcp/.github/workflows/02.deploy_manually.yaml new file mode 100644 index 0000000..db5c0a1 --- /dev/null +++ b/gcp/.github/workflows/02.deploy_manually.yaml @@ -0,0 +1,52 @@ +name: 02. Deploy Manually + +permissions: + id-token: write + contents: read + +on: + workflow_dispatch: + inputs: + environment: + description: "Environment" + required: true + default: "production" + type: choice + options: + - production + +jobs: + deploy-production: + name: Deploy to production + if: ${{ github.event.inputs.environment == 'production' }} + concurrency: + group: production_environment + cancel-in-progress: true + runs-on: ubuntu-latest + environment: + name: production + url: https://jetrockets.com + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_branch }} + + - name: Setup + uses: ./.github/workflows/setup + id: setup + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + gcp_credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' + gcp_registry_username: '' + + - name: Kamal Deploy + uses: igor-alexandrov/kamal-deploy@v0.1.3 + with: + registry-username: '' + registry-password: ${{ steps.setup.outputs.kamal-registry-password }} + environment: production + env: + DATABASE_URL: ${{ secrets.DATABASE_URL }} + REDIS_URL: ${{ secrets.REDIS_URL }} + RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} diff --git a/gcp/.github/workflows/03.kamal_run_command.yaml b/gcp/.github/workflows/03.kamal_run_command.yaml new file mode 100644 index 0000000..0517db7 --- /dev/null +++ b/gcp/.github/workflows/03.kamal_run_command.yaml @@ -0,0 +1,56 @@ +name: 03. Kamal run command + +permissions: + id-token: write + contents: read + +on: + workflow_dispatch: + inputs: + command: + description: 'Commands' + required: true + type: choice + options: + - proxy reboot --rolling -y + - upgrade --rolling -y + - accessory boot all + # - downgrade --rolling -y + environment: + description: 'Environment' + required: true + type: choice + options: + - production + +jobs: + kamal_run_command: + name: Kamal run command + runs-on: ubuntu-latest + timeout-minutes: 20 + concurrency: + group: ${{ github.event.inputs.environment }}_environment + cancel-in-progress: false + environment: + name: ${{ github.event.inputs.environment }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_branch }} + + - uses: ./.github/workflows/setup + name: Setup + id: setup + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + gcp_credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' + + - name: kamal ${{ github.event.inputs.command }} --destination=${{ github.event.inputs.environment }} + env: + KAMAL_REGISTRY_PASSWORD: ${{ steps.setup.outputs.kamal-registry-password }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} + REDIS_URL: ${{ secrets.REDIS_URL }} + RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} + DOCKER_BUILDKIT: 1 + run: | + ./bin/kamal ${{ github.event.inputs.command }} --destination=${{ github.event.inputs.environment }} diff --git a/gcp/.github/workflows/setup/action.yaml b/gcp/.github/workflows/setup/action.yaml new file mode 100644 index 0000000..647a7c4 --- /dev/null +++ b/gcp/.github/workflows/setup/action.yaml @@ -0,0 +1,49 @@ +name: Setup + +inputs: + gcp_credentials_json: + description: GCP Role Access + required: true + gcp_registry_username: + description: GCP registry user + required: true + ssh-private-key: + description: SSH Private Key + required: true + +outputs: + kamal-registry-password: + description: Kamal Registry Password + value: ${{ steps.auth.outputs.access_token }} + +runs: + using: composite + steps: + - uses: ruby/setup-ruby@v1 + env: + BUNDLE_GEMFILE: ./Gemfile + with: + ruby-version: .ruby-version + bundler-cache: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ inputs.ssh-private-key }} + + - name: Google Auth + id: auth + uses: 'google-github-actions/auth@v2' + with: + token_format: access_token + credentials_json: '${{ inputs.gcp_credentials_json }}' + + - name: Docker Auth + id: docker-auth + uses: 'docker/login-action@v3' + with: + username: '${{ inputs.gcp_registry_username }}' + password: '${{ steps.auth.outputs.access_token }}' + registry: '' diff --git a/gcp/.kamal/secrets-common b/gcp/.kamal/secrets-common new file mode 100644 index 0000000..157f573 --- /dev/null +++ b/gcp/.kamal/secrets-common @@ -0,0 +1,7 @@ +KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD +KAMAL_REGISTRY_USERNAME=$KAMAL_REGISTRY_USERNAME +RAILS_MASTER_KEY=$RAILS_MASTER_KEY +DATABASE_URL=$DATABASE_URL +REDIS_URL=$REDIS_URL +PGHERO_USERNAME=$PGHERO_USERNAME +PGHERO_PASSWORD=$PGHERO_PASSWORD \ No newline at end of file diff --git a/gcp/config/deploy.production.yml b/gcp/config/deploy.production.yml new file mode 100644 index 0000000..610dfbb --- /dev/null +++ b/gcp/config/deploy.production.yml @@ -0,0 +1,14 @@ +# Deploy to these servers. +servers: + web: + hosts: + - <%= SERVER_IP %> + + # sidekiq: + # cmd: bin/sidekiq + # hosts: + # - <%= SERVER_IP %> + +builder: + args: + RAILS_ENV: production diff --git a/gcp/config/deploy.yml b/gcp/config/deploy.yml new file mode 100644 index 0000000..374a481 --- /dev/null +++ b/gcp/config/deploy.yml @@ -0,0 +1,47 @@ +# Name of your application. Used to uniquely configure containers. +service: + +# Name of the container image. +image: + +# Use a different ssh user than root +ssh: + user: www + +# Credentials for your image host. +registry: + server: us-central1-docker.pkg.dev/<%=PROJECT_ID%>/reponame + + username: + - KAMAL_REGISTRY_USERNAME + password: + - KAMAL_REGISTRY_PASSWORD + +# Container builder setup. +builder: + arch: amd64 + args: + RUBY_VERSION: <%= File.read('.ruby-version').strip %> + # NODE_VERSION: 18.15.0 + # YARN_VERSION: 1.22.21 + cache: + type: registry + options: mode=max,image-manifest=true,oci-mediatypes=true + +env: + clear: + RAILS_LOG_TO_STDOUT: 1 + RAILS_SERVE_STATIC_FILES: 1 + RAILS_ENV: production + secret: + - RAILS_MASTER_KEY + - DATABASE_URL + - REDIS_URL + +accessories: + redis: + image: "redis:alpine" + roles: + - sidekiq + volumes: + - ~/docker_redis_data:/data \ No newline at end of file