Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/docker-gar.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Build and Push to Google Artifact Registry

on:
push:
tags:
- "v*.*.*"

permissions:
contents: read
id-token: write

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive

- name: Create .version file
env:
REF_TYPE: ${{ github.ref_type }}
REF_NAME: ${{ github.ref_name }}
COMMIT_SHA: ${{ github.sha }}
run: |
if [[ "${REF_TYPE}" == "tag" ]]; then
echo "${REF_NAME}" > .version
else
echo "${COMMIT_SHA}" > .version
fi

- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
token_format: access_token

- name: Login to Artifact Registry
uses: docker/login-action@v3
with:
registry: us-central1-docker.pkg.dev
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: us-central1-docker.pkg.dev/kencove-prod/docuseal/docuseal
tags: |
type=semver,pattern={{version}}
type=sha,prefix=,format=short
type=raw,value=latest,enable={{is_default_branch}}
Comment on lines +55 to +58
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

docker metadata-action is_default_branch template variable tag push behavior

💡 Result:

In docker/metadata-action, {{is_default_branch}} is only about the branch ref that triggered the workflow run (i.e., a refs/heads/... run). It returns true only when the workflow was triggered by the repo’s default branch; otherwise false. (github.com)

That means on a tag push run (refs/tags/...), there is no triggering branch ref (e.g., {{branch}} is empty on tag runs), so {{is_default_branch}} is not a reliable way to detect “tag created from default branch”. (github.com)

If your goal is “push latest only for default branch builds”:

  • Do it on branch push runs with a conditional raw tag, e.g. type=raw,value=latest,enable={{is_default_branch}}. (github.com)

If your goal is “push latest on release tags”:

  • Rely on the action’s built-in latest tag handling (flavor: latest=auto by default), which generates latest for tag/semver/match-style tag strategies. (github.com)

Finally, while {{base_ref}} may sometimes show something on tag push payloads, the action explicitly warns it doesn’t always return the expected branch on tag pushes and is not recommended to rely on for this purpose. (github.com)

Citations:


The latest tag may never be applied on tag-triggered workflows.

When this workflow is triggered by a tag push, github.ref is refs/tags/v*.*.*, not a branch ref. The is_default_branch template in docker/metadata-action evaluates whether the current ref is the default branch—which is false for tag pushes. This means the latest tag will never be applied.

If you want latest to be applied when tagging, consider one of these approaches:

  1. Use the action's built-in latest tag handling by setting flavor: latest=auto (applies latest for tag/semver tag strategies)
  2. Always apply latest on semver tags: type=raw,value=latest
  3. Remove the latest tag line if it's not needed
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docker-gar.yml around lines 55 - 58, The workflow's tags
block uses "type=raw,value=latest,enable={{is_default_branch}}" which prevents
the latest tag from being applied on tag-triggered runs (github.ref for tags
isn't the default branch); update the docker/metadata-action configuration so
latest is applied for semver/tag pushes—either replace the conditional with the
action's automatic handling by adding "flavor: latest=auto" to the
metadata-action invocation, or make the latest tag unconditional by using
"type=raw,value=latest", or remove the latest line if not desired; edit the tags
block (the line containing type=raw,value=latest and the
enable={{is_default_branch}}) or add the flavor setting to implement your chosen
approach.


- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ gem 'jwt', require: false
gem 'lograge'
gem 'numo-narray-alt', require: false
gem 'oj'
gem 'omniauth-google-oauth2'
gem 'omniauth-rails_csrf_protection'
gem 'onnxruntime', require: false
gem 'pagy'
gem 'pg', require: false
Expand Down
38 changes: 38 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ GEM
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
hashdiff (1.2.1)
hashie (5.1.0)
logger
hexapdf (1.5.0)
cmdparse (~> 3.0, >= 3.0.3)
geom2d (~> 0.4, >= 0.4.1)
Expand Down Expand Up @@ -326,6 +328,8 @@ GEM
prism (~> 1.5)
msgpack (1.8.0)
multi_json (1.19.1)
multi_xml (0.8.1)
bigdecimal (>= 3.1, < 5)
net-http (0.9.1)
uri (>= 0.11.1)
net-imap (0.6.2)
Expand All @@ -349,9 +353,33 @@ GEM
nokogiri (1.19.0-x86_64-linux-musl)
racc (~> 1.4)
numo-narray-alt (0.9.13)
oauth2 (2.0.18)
faraday (>= 0.17.3, < 4.0)
jwt (>= 1.0, < 4.0)
logger (~> 1.2)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
snaky_hash (~> 2.0, >= 2.0.3)
version_gem (~> 1.1, >= 1.1.9)
oj (3.16.13)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (2.1.4)
hashie (>= 3.4.6)
logger
rack (>= 2.2.3)
rack-protection
omniauth-google-oauth2 (1.2.1)
jwt (>= 2.9.2)
oauth2 (~> 2.0)
omniauth (~> 2.0)
omniauth-oauth2 (~> 1.8)
omniauth-oauth2 (1.9.0)
oauth2 (>= 2.0.2, < 3)
omniauth (~> 2.0)
omniauth-rails_csrf_protection (2.0.1)
actionpack (>= 4.2)
omniauth (~> 2.0)
onnxruntime (0.10.1)
ffi
onnxruntime (0.10.1-aarch64-linux)
Expand Down Expand Up @@ -406,6 +434,10 @@ GEM
nio4r (~> 2.0)
racc (1.8.1)
rack (3.2.4)
rack-protection (4.2.1)
base64 (>= 0.1.0)
logger (>= 1.6.0)
rack (>= 3.0.0, < 4)
rack-proxy (0.7.7)
rack
rack-session (2.1.1)
Expand Down Expand Up @@ -558,6 +590,9 @@ GEM
simplecov-html (0.13.2)
simplecov_json_formatter (0.1.4)
smart_properties (1.17.0)
snaky_hash (2.0.3)
hashie (>= 0.1.0, < 6)
version_gem (>= 1.1.8, < 3)
sqlite3 (2.9.0-aarch64-linux-gnu)
sqlite3 (2.9.0-aarch64-linux-musl)
sqlite3 (2.9.0-arm64-darwin)
Expand Down Expand Up @@ -590,6 +625,7 @@ GEM
uniform_notifier (1.18.0)
uri (1.1.1)
useragent (0.16.11)
version_gem (1.1.9)
warden (1.2.9)
rack (>= 2.0.9)
web-console (4.2.1)
Expand Down Expand Up @@ -652,6 +688,8 @@ DEPENDENCIES
lograge
numo-narray-alt
oj
omniauth-google-oauth2
omniauth-rails_csrf_protection
onnxruntime
pagy
pg
Expand Down
19 changes: 19 additions & 0 deletions app/controllers/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_action :verify_authenticity_token, only: :google_oauth2

def google_oauth2
user = Users.from_omniauth(request.env['omniauth.auth'])

if user&.active_for_authentication?
sign_in_and_redirect(user, event: :authentication)
else
redirect_to new_user_session_path, alert: I18n.t('user_not_found')
end
end

def failure
redirect_to new_user_session_path, alert: I18n.t('authentication_failed')
end
end
1 change: 1 addition & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class User < ApplicationRecord
has_many :email_messages, dependent: :destroy, foreign_key: :author_id, inverse_of: :author

devise :two_factor_authenticatable, :recoverable, :rememberable, :validatable, :trackable, :lockable
devise :omniauthable, omniauth_providers: [:google_oauth2] if ENV['GOOGLE_CLIENT_ID'].present?

attribute :role, :string, default: ADMIN_ROLE
attribute :uuid, :string, default: -> { SecureRandom.uuid }
Expand Down
7 changes: 7 additions & 0 deletions config/initializers/devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,13 @@ def devise_mail(record, action, opts = {}, &)
# changed. Defaults to true, so a user is signed in automatically after changing a password.
# config.sign_in_after_change_password = true

if ENV['GOOGLE_CLIENT_ID'].present?
config.omniauth :google_oauth2,
ENV.fetch('GOOGLE_CLIENT_ID'),
ENV.fetch('GOOGLE_CLIENT_SECRET'),
{ hd: ENV.fetch('GOOGLE_HOSTED_DOMAIN', 'kencove.com') }
end

ActiveSupport.run_load_hooks(:devise_config, config)
end
# rubocop:enable Metrics/BlockLength
2 changes: 2 additions & 0 deletions config/locales/i18n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ en: &en
sign_in: Sign In
signing_in: Signing In
sign_in_with_microsoft: Sign in with Microsoft
user_not_found: User not found. Please contact your administrator.
authentication_failed: Authentication failed. Please try again.
Comment on lines +176 to +177
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add translations for non‑English locales.

These new keys are only present in en. If other locales are active, they’ll render as missing translations. Please add equivalent keys for each supported locale or confirm a fallback strategy.

🤖 Prompt for AI Agents
In `@config/locales/i18n.yml` around lines 176 - 177, The new i18n keys
user_not_found and authentication_failed were added only for English; update all
supported locale YAML files to include equivalent translations for these keys
(or add them to the locale fallback file) so missing-translation errors don't
occur; locate the locale files that mirror i18n.yml (e.g., the other locale
YAMLs or the default fallback locale) and add matching keys with appropriate
translated messages, or confirm/update the app's I18n.fallbacks configuration to
ensure these keys resolve to the English strings when a locale translation is
absent.

sign_in_with_google: Sign in with Google
forgot_your_password_: Forgot your password?
create_free_account: Create free account
Expand Down
11 changes: 9 additions & 2 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@
get 'up' => 'rails/health#show'
get 'manifest' => 'pwa#manifest'

devise_for :users, path: '/', only: %i[sessions passwords],
controllers: { sessions: 'sessions', passwords: 'passwords' }
devise_actions = %i[sessions passwords]
devise_controllers = { sessions: 'sessions', passwords: 'passwords' }

if ENV['GOOGLE_CLIENT_ID'].present?
devise_actions << :omniauth_callbacks
devise_controllers[:omniauth_callbacks] = 'omniauth_callbacks'
end

devise_for :users, path: '/', only: devise_actions, controllers: devise_controllers

devise_scope :user do
resource :invitation, only: %i[update] do
Expand Down
9 changes: 9 additions & 0 deletions lib/users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module Users
module_function

def from_omniauth(oauth)
User.find_by(email: oauth.info.email.to_s.downcase)
end
end
Loading