diff --git a/.serena/memories/workflow/creating-prs.md b/.serena/memories/workflow/creating-prs.md index a92c199e22..fa94a9afe0 100644 --- a/.serena/memories/workflow/creating-prs.md +++ b/.serena/memories/workflow/creating-prs.md @@ -1,6 +1,12 @@ # Creating Pull Requests -PR only on explicit request. Branch: issue/feature-specific; fallback `/` (`fix/...`, `feat/...`, `refactor/...`, `docs/...`, `chore/...`, `perf/...`). +PR only on explicit request. + +## Branch Naming + +- Primary: `issue-NNNN` — one branch per GitHub issue (e.g. `issue-11525`). +- No issue: free-form descriptive name, dash-separated, no slashes (e.g. `fix-ellipse-icon-typo`, `feat-auto-link-libraries`). +- If the user already created the branch, use it as-is — never rename. ## Target Branch diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 63b931900f..d905aae9e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,6 +14,7 @@ Center](https://help.penpot.app/). - [Reporting Bugs](#reporting-bugs) - [Pull Requests](#pull-requests) - [Workflow](#workflow) + - [Branch naming](#branch-naming) - [Format](#format) - [Title format](#title-format) - [Description](#description) @@ -73,6 +74,18 @@ Advisories](https://github.com/penpot/penpot/security/advisories) 4. **Format and lint** — run the checks described in [Formatting and Linting](#formatting-and-linting) before submitting. +### Branch naming + +Branch names are not enforced, but we recommend the following: + +- **`issue-NNNN`** — when working from a GitHub issue, name the branch after + it (e.g. `issue-11525`). This makes each PR's origin self-evident. +- Otherwise, use a short, descriptive name with words separated by hyphens + and no slashes (e.g. `fix-ellipse-icon-typo`, `feat-auto-link-libraries`). + +Since PRs are squash-merged, the branch name does not survive into the +commit history — what matters is the [PR title](#title-format). + ### Format #### Title diff --git a/backend/src/app/rpc/commands/demo.clj b/backend/src/app/rpc/commands/demo.clj index 3ac726128f..c21ae33838 100644 --- a/backend/src/app/rpc/commands/demo.clj +++ b/backend/src/app/rpc/commands/demo.clj @@ -9,6 +9,7 @@ (:require [app.auth :refer [derive-password-weak]] [app.common.exceptions :as ex] + [app.common.schema :as sm] [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] @@ -21,14 +22,21 @@ [buddy.core.codecs :as bc] [buddy.core.nonce :as bn])) +(def ^:private + schema:create-demo-profile + [:map + [:skip-onboarding {:optional true} ::sm/boolean]]) + (sv/defmethod ::create-demo-profile "A command that is responsible of creating a demo purpose profile. It only works if the `demo-users` flag is enabled in the configuration." {::rpc/auth false ::doc/added "1.15" - ::doc/changes ["1.15" "This method is migrated from mutations to commands."]} - [cfg _] + ::doc/changes [["1.15" "This method is migrated from mutations to commands."] + ["2.18" "Add optional `skip-onboarding` param. When true, the profile is created with `onboarding-viewed` and `release-notes-viewed` (current version) set, skipping the onboarding flow."]] + ::sm/params schema:create-demo-profile} + [cfg {:keys [skip-onboarding]}] (when-not (contains? cf/flags :demo-users) (ex/raise :type :validation @@ -48,7 +56,13 @@ :is-active true :is-demo true :password (derive-password-weak password) - :props {}} + :props (cond-> {} + skip-onboarding (assoc :onboarding-viewed true + ;; Redundant today: auth/create-profile + ;; overwrites this with the current + ;; version, kept so the skip does not + ;; depend on that default. + :release-notes-viewed (:main cf/version)))} profile (db/tx-run! cfg (fn [cfg] (->> (auth/create-profile cfg params) (auth/create-profile-rels cfg))))] diff --git a/backend/test/backend_tests/rpc_demo_test.clj b/backend/test/backend_tests/rpc_demo_test.clj index d990ec8a32..3bda13fc61 100644 --- a/backend/test/backend_tests/rpc_demo_test.clj +++ b/backend/test/backend_tests/rpc_demo_test.clj @@ -8,6 +8,7 @@ (:require [app.auth :as auth] [app.config :as cf] + [app.rpc.commands.profile :as profile] [backend-tests.helpers :as th] [clojure.test :as t])) @@ -38,3 +39,38 @@ (with-redefs [cf/flags (disj cf/flags :demo-users)] (let [{:keys [error]} (th/command! {::th/type :create-demo-profile})] (t/is (th/ex-of-code? error :demo-users-not-allowed))))) + +(t/deftest create-demo-profile-keeps-onboarding-by-default + (with-redefs [cf/flags (conj cf/flags :demo-users)] + (let [{:keys [error result]} (th/command! {::th/type :create-demo-profile})] + (t/is (nil? error)) + (let [saved (th/db-get :profile {:email (:email result)}) + decoded (profile/decode-row saved)] + (t/is (nil? (get-in decoded [:props :onboarding-viewed]))))))) + +(t/deftest create-demo-profile-skips-onboarding-when-requested + (with-redefs [cf/flags (conj cf/flags :demo-users)] + (let [{:keys [error result]} (th/command! {::th/type :create-demo-profile + :skip-onboarding true})] + (t/is (nil? error)) + (let [saved (th/db-get :profile {:email (:email result)}) + decoded (profile/decode-row saved)] + (t/is (true? (get-in decoded [:props :onboarding-viewed]))) + (t/is (= (:main cf/version) + (get-in decoded [:props :release-notes-viewed]))))))) + +(t/deftest create-demo-profile-explicit-false-keeps-onboarding + (with-redefs [cf/flags (conj cf/flags :demo-users)] + (let [{:keys [error result]} (th/command! {::th/type :create-demo-profile + :skip-onboarding false})] + (t/is (nil? error)) + (let [saved (th/db-get :profile {:email (:email result)}) + decoded (profile/decode-row saved)] + (t/is (nil? (get-in decoded [:props :onboarding-viewed]))))))) + +(t/deftest create-demo-profile-rejects-non-boolean-skip-onboarding + (with-redefs [cf/flags (conj cf/flags :demo-users)] + (let [{:keys [error]} (th/command! {::th/type :create-demo-profile + :skip-onboarding "yes"})] + (t/is (th/ex-of-type? error :validation)) + (t/is (th/ex-of-code? error :params-validation)))))