diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index e5170124555cd60db28965bf392b11c66b5e2c16..e9697e14c4c4a56b9b01f157ab352851dc06f6c0 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -31466,7 +31466,7 @@ Project-level settings for product analytics provider.
| `requestAccessEnabled` | [`Boolean`](#boolean) | Indicates if users can request member access to the project. |
| `requirementStatesCount` | [`RequirementStatesCount`](#requirementstatescount) | Number of requirements for the project by their state. |
| `sastCiConfiguration` | [`SastCiConfiguration`](#sastciconfiguration) | SAST CI configuration for the project. |
-| `savedReplies` **{warning-solid}** | [`ProjectSavedReplyConnection`](#projectsavedreplyconnection) | **Introduced** in GitLab 16.11. **Status**: Experiment. Saved replies available to the project. Available only when feature flag `project_saved_replies_flag` is enabled. |
+| `savedReplies` | [`ProjectSavedReplyConnection`](#projectsavedreplyconnection) | Saved replies available to the project. (see [Connections](#connections)) |
| `securityDashboardPath` | [`String`](#string) | Path to project's security dashboard. |
| `securityPolicyProject` | [`Project`](#project) | Security policy project assigned to the project, absent if assigned to a parent group. |
| `securityPolicyProjectLinkedGroups` | [`GroupConnection`](#groupconnection) | Groups linked to the project, when used as Security Policy Project. (see [Connections](#connections)) |
@@ -33005,11 +33005,7 @@ four standard [pagination arguments](#pagination-arguments):
##### `Project.savedReply`
-Saved reply in the project. Available only when feature flag `group_saved_replies_flag` is enabled.
-
-DETAILS:
-**Introduced** in GitLab 16.11.
-**Status**: Experiment.
+Saved reply in the project.
Returns [`ProjectSavedReply`](#projectsavedreply).
diff --git a/doc/user/profile/comment_templates.md b/doc/user/profile/comment_templates.md
index 97ecd30735d5e6e5473bc038479741912fbbfb77..e6283892be8dae14e4fde96a1d47635046466a76 100644
--- a/doc/user/profile/comment_templates.md
+++ b/doc/user/profile/comment_templates.md
@@ -18,6 +18,7 @@ DETAILS:
> - Group-level saved replies [enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/440817) on GitLab.com and self-managed in GitLab 16.11.
> - Group-level saved replies [generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148958) in GitLab 17.0. Feature flag `group_saved_replies_flag` removed.
> - Project-level saved replies [introduced](https://gitlab.com/groups/gitlab-org/-/epics/12669) in GitLab 17.0 [with a flag](../../administration/feature_flags.md) named `project_saved_replies_flag`. Enabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/504028) in GitLab 17.7. Feature flag `project_saved_replies_flag` removed.
FLAG:
The availability of Project-level saved replies is controlled by a feature flag.
diff --git a/ee/app/graphql/ee/types/project_type.rb b/ee/app/graphql/ee/types/project_type.rb
index cde80aaf72a6aefd0e19df50566f064d5956f748..17259e5cc4cf2ad3bbff0cd28cfa9a3d6c76407a 100644
--- a/ee/app/graphql/ee/types/project_type.rb
+++ b/ee/app/graphql/ee/types/project_type.rb
@@ -496,15 +496,11 @@ module ProjectType
field :saved_replies,
::Types::Projects::SavedReplyType.connection_type,
null: true,
- description: 'Saved replies available to the project. Available only when feature flag ' \
- '`project_saved_replies_flag` is enabled.',
- experiment: { milestone: '16.11' }
+ description: 'Saved replies available to the project.'
field :saved_reply,
resolver: ::Resolvers::Projects::SavedReplyResolver,
- description: 'Saved reply in the project. Available only when feature flag ' \
- '`group_saved_replies_flag` is enabled.',
- experiment: { milestone: '16.11' }
+ description: 'Saved reply in the project.'
field :merge_trains,
::Types::MergeTrains::TrainType.connection_type,
diff --git a/ee/app/models/ee/project.rb b/ee/app/models/ee/project.rb
index de026c60daffd9d5f620df97e64d1fa1492e1352..2c48b9445349948de5b7c7757e040b9476e93291 100644
--- a/ee/app/models/ee/project.rb
+++ b/ee/app/models/ee/project.rb
@@ -1376,7 +1376,7 @@ def on_demand_dast_available?
override :supports_saved_replies?
def supports_saved_replies?
- ::Feature.enabled?(:project_saved_replies_flag, self, type: :beta) && licensed_feature_available?(:project_saved_replies)
+ licensed_feature_available?(:project_saved_replies)
end
# Temporary code to facilitate: https://gitlab.com/gitlab-org/gitlab/-/issues/431346
diff --git a/ee/config/feature_flags/beta/project_saved_replies_flag.yml b/ee/config/feature_flags/beta/project_saved_replies_flag.yml
deleted file mode 100644
index 7d0ef8296a181bafc5bd6b48a1b562ea93e566a4..0000000000000000000000000000000000000000
--- a/ee/config/feature_flags/beta/project_saved_replies_flag.yml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-name: project_saved_replies_flag
-feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/440818
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147786
-rollout_issue_url:
-milestone: '16.11'
-group: group::code review
-type: beta
-default_enabled: true
diff --git a/ee/spec/models/ee/project_spec.rb b/ee/spec/models/ee/project_spec.rb
index 353b5b5297421fd529dd551ba3db8eb6ae095848..ab36f48632799d80d906f84c44aabddbfd8d19c3 100644
--- a/ee/spec/models/ee/project_spec.rb
+++ b/ee/spec/models/ee/project_spec.rb
@@ -4878,15 +4878,6 @@ def stub_default_url_options(host)
describe '#supports_saved_replies?' do
subject(:supported) { project.supports_saved_replies? }
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
- end
-
- it { is_expected.to eq(false) }
- end
-
context 'when license is invalid' do
before do
stub_licensed_features(project_saved_replies: false)
diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb
index 2922771e2b38a162874aacba1609356fafcfbc6d..62769939784dbfee14abfeaa906181a232c2ce04 100644
--- a/ee/spec/policies/project_policy_spec.rb
+++ b/ee/spec/policies/project_policy_spec.rb
@@ -4235,14 +4235,6 @@ def create_member_role(member, abilities = member_role_abilities)
context 'saved replies permissions' do
let(:current_user) { owner }
- context 'when project_saved_replies_flag feature flag is disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- end
-
- it { is_expected.to be_disallowed(:read_saved_replies, :create_saved_replies, :update_saved_replies, :destroy_saved_replies) }
- end
-
context 'when no license is present' do
before do
stub_licensed_features(project_saved_replies: false)
diff --git a/ee/spec/requests/api/graphql/projects/saved_replies/create_spec.rb b/ee/spec/requests/api/graphql/projects/saved_replies/create_spec.rb
index 748343019a2b87adab41ffc72b50421bb64ee8d1..68f979f3b8c318397f969b816ac7c631bb6133b8 100644
--- a/ee/spec/requests/api/graphql/projects/saved_replies/create_spec.rb
+++ b/ee/spec/requests/api/graphql/projects/saved_replies/create_spec.rb
@@ -13,19 +13,6 @@
let(:mutation) { graphql_mutation(:project_saved_reply_create, input) }
let(:mutation_response) { graphql_mutation_response(:project_saved_reply_create) }
- context 'with project_saved_replies_flag disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
- end
-
- it 'returns null' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(mutation_response).to be_nil
- end
- end
-
context 'when license is invalid' do
before do
stub_licensed_features(project_saved_replies: false)
diff --git a/ee/spec/requests/api/graphql/projects/saved_replies/destroy_spec.rb b/ee/spec/requests/api/graphql/projects/saved_replies/destroy_spec.rb
index c41b267bb16a9af822b2b8a50574107d4007d7d1..6903ea67fd9f331374b64c6f1d09113b36fbaa94 100644
--- a/ee/spec/requests/api/graphql/projects/saved_replies/destroy_spec.rb
+++ b/ee/spec/requests/api/graphql/projects/saved_replies/destroy_spec.rb
@@ -14,19 +14,6 @@
let(:mutation) { graphql_mutation(:project_saved_reply_destroy, input) }
let(:mutation_response) { graphql_mutation_response(:project_saved_reply_destroy) }
- context 'with project_saved_replies_flag disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
- end
-
- it 'returns null' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(mutation_response).to be_nil
- end
- end
-
context 'when license is invalid' do
before do
stub_licensed_features(project_saved_replies: false)
diff --git a/ee/spec/requests/api/graphql/projects/saved_replies/update_spec.rb b/ee/spec/requests/api/graphql/projects/saved_replies/update_spec.rb
index 4aa2b2bfc2f84cf7627c643cac25c2b1a81b3788..bcd8be94727f244aaf9eb928117cbd4449e94d96 100644
--- a/ee/spec/requests/api/graphql/projects/saved_replies/update_spec.rb
+++ b/ee/spec/requests/api/graphql/projects/saved_replies/update_spec.rb
@@ -14,19 +14,6 @@
let(:mutation) { graphql_mutation(:project_saved_reply_update, input) }
let(:mutation_response) { graphql_mutation_response(:project_saved_reply_update) }
- context 'with project_saved_replies_flag disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
- end
-
- it 'returns null' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(mutation_response).to be_nil
- end
- end
-
context 'when license is invalid' do
before do
stub_licensed_features(project_saved_replies: false)
diff --git a/ee/spec/requests/api/graphql/projects/saved_reply_spec.rb b/ee/spec/requests/api/graphql/projects/saved_reply_spec.rb
index 156506b66ff9fc9bbaf83f0fd2b7d7d530c14b09..563c312da098d8db4f5032db4bc0b0276e76980d 100644
--- a/ee/spec/requests/api/graphql/projects/saved_reply_spec.rb
+++ b/ee/spec/requests/api/graphql/projects/saved_reply_spec.rb
@@ -48,19 +48,6 @@
end
end
- context 'when project_saved_replies_flag feature flag is disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
- end
-
- it 'returns null' do
- post_query
-
- expect(saved_reply_graphl_response).to be_nil
- end
- end
-
context 'when license is valid' do
before do
stub_licensed_features(project_saved_replies: true)
diff --git a/ee/spec/requests/projects/comment_templates_controller_spec.rb b/ee/spec/requests/projects/comment_templates_controller_spec.rb
index 845b1268292e8c52c1d458c8dab9aa2945dfd679..d90868c771b3b3c4c3434d930f39d878a75db40f 100644
--- a/ee/spec/requests/projects/comment_templates_controller_spec.rb
+++ b/ee/spec/requests/projects/comment_templates_controller_spec.rb
@@ -18,17 +18,6 @@
it { expect(response).to have_gitlab_http_status(:not_found) }
end
- context 'when project_saved_replies_flag feature flag is disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
-
- get project_comment_templates_path(project)
- end
-
- it { expect(response).to have_gitlab_http_status(:not_found) }
- end
-
context 'when license is valid' do
before do
stub_licensed_features(project_saved_replies: true)
@@ -61,17 +50,6 @@
it { expect(response).to have_gitlab_http_status(:not_found) }
end
- context 'when project_saved_replies_flag feature flag is disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
-
- get project_comment_templates_path(project)
- end
-
- it { expect(response).to have_gitlab_http_status(:not_found) }
- end
-
context 'when license is valid' do
before do
stub_licensed_features(project_saved_replies: true)
@@ -104,17 +82,6 @@
it { expect(response).to have_gitlab_http_status(:not_found) }
end
- context 'when project_saved_replies_flag feature flag is disabled' do
- before do
- stub_feature_flags(project_saved_replies_flag: false)
- stub_licensed_features(project_saved_replies: true)
-
- get project_comment_templates_path(project)
- end
-
- it { expect(response).to have_gitlab_http_status(:not_found) }
- end
-
context 'when license is valid' do
before do
stub_licensed_features(project_saved_replies: true)