Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1f794fa428
commit
ba2d791767
9 changed files with 111 additions and 51 deletions
|
@ -7,6 +7,12 @@ import { s__ } from '~/locale';
|
|||
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
|
||||
import { RUNNER_TAG_BG_CLASS } from '../../constants';
|
||||
|
||||
// TODO This should be implemented via a GraphQL API
|
||||
// The API should
|
||||
// 1) scope to the rights of the user
|
||||
// 2) stay up to date to the removal of old tags
|
||||
// 3) consider the scope of search, like searching within the tags of a group
|
||||
// See: https://gitlab.com/gitlab-org/gitlab/-/issues/333796
|
||||
export const TAG_SUGGESTIONS_PATH = '/admin/runners/tag_list.json';
|
||||
|
||||
export default {
|
||||
|
@ -29,12 +35,6 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
getTagsOptions(search) {
|
||||
// TODO This should be implemented via a GraphQL API
|
||||
// The API should
|
||||
// 1) scope to the rights of the user
|
||||
// 2) stay up to date to the removal of old tags
|
||||
// 3) consider the scope of search, like searching within the tags of a group
|
||||
// See: https://gitlab.com/gitlab-org/gitlab/-/issues/333796
|
||||
return axios
|
||||
.get(TAG_SUGGESTIONS_PATH, {
|
||||
params: {
|
||||
|
@ -46,6 +46,12 @@ export default {
|
|||
});
|
||||
},
|
||||
async fetchTags(searchTerm) {
|
||||
// Note: Suggestions should only be enabled for admin users
|
||||
if (this.config.suggestionsDisabled) {
|
||||
this.tags = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
this.tags = await this.getTagsOptions(searchTerm);
|
||||
|
|
|
@ -10,6 +10,7 @@ query getGroupRunners(
|
|||
$paused: Boolean
|
||||
$status: CiRunnerStatus
|
||||
$type: CiRunnerType
|
||||
$tagList: [String!]
|
||||
$search: String
|
||||
$sort: CiRunnerSort
|
||||
) {
|
||||
|
@ -24,6 +25,7 @@ query getGroupRunners(
|
|||
paused: $paused
|
||||
status: $status
|
||||
type: $type
|
||||
tagList: $tagList
|
||||
search: $search
|
||||
sort: $sort
|
||||
) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import RunnerMembershipToggle from '../components/runner_membership_toggle.vue';
|
|||
|
||||
import { pausedTokenConfig } from '../components/search_tokens/paused_token_config';
|
||||
import { statusTokenConfig } from '../components/search_tokens/status_token_config';
|
||||
import { tagTokenConfig } from '../components/search_tokens/tag_token_config';
|
||||
import {
|
||||
GROUP_FILTERED_SEARCH_NAMESPACE,
|
||||
GROUP_TYPE,
|
||||
|
@ -131,12 +132,20 @@ export default {
|
|||
noRunnersFound() {
|
||||
return !this.runnersLoading && !this.runners.items.length;
|
||||
},
|
||||
searchTokens() {
|
||||
return [pausedTokenConfig, statusTokenConfig, upgradeStatusTokenConfig];
|
||||
},
|
||||
filteredSearchNamespace() {
|
||||
return `${GROUP_FILTERED_SEARCH_NAMESPACE}/${this.groupFullPath}`;
|
||||
},
|
||||
searchTokens() {
|
||||
return [
|
||||
pausedTokenConfig,
|
||||
statusTokenConfig,
|
||||
{
|
||||
...tagTokenConfig,
|
||||
suggestionsDisabled: true,
|
||||
},
|
||||
upgradeStatusTokenConfig,
|
||||
];
|
||||
},
|
||||
isSearchFiltered() {
|
||||
return isSearchFiltered(this.search);
|
||||
},
|
||||
|
|
|
@ -19,7 +19,7 @@ Terraform to define resources that you can version, reuse, and share:
|
|||
|
||||
## Integrate your project with Terraform
|
||||
|
||||
> SAST test was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/6655) in GitLab 14.6.
|
||||
> IaC Scanning was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/6655) in GitLab 14.6.
|
||||
|
||||
The integration with GitLab and Terraform happens through GitLab CI/CD.
|
||||
Use an `include` attribute to add the Terraform template to your project and
|
||||
|
@ -35,7 +35,7 @@ All templates:
|
|||
- Use the [GitLab-managed Terraform state](terraform_state.md) as the Terraform state storage backend.
|
||||
- Trigger four pipeline stages: `test`, `validate`, `build`, and `deploy`.
|
||||
- Run Terraform commands: `test`, `validate`, `plan`, and `plan-json`. It also runs the `apply` only on the default branch.
|
||||
- Run the [Terraform SAST scanner](../../application_security/iac_scanning/index.md#configure-iac-scanning-manually).
|
||||
- Check for security problems using [IaC Scanning](../../application_security/iac_scanning/index.md#configure-iac-scanning-manually).
|
||||
|
||||
### Latest Terraform template
|
||||
|
||||
|
|
|
@ -351,14 +351,15 @@ RSpec.describe "Admin Runners" do
|
|||
end
|
||||
|
||||
describe 'filter by tag' do
|
||||
before_all do
|
||||
create(:ci_runner, :instance, description: 'runner-blue', tag_list: ['blue'])
|
||||
create(:ci_runner, :instance, description: 'runner-red', tag_list: ['red'])
|
||||
let_it_be(:runner_1) { create(:ci_runner, :instance, description: 'runner-blue', tag_list: ['blue']) }
|
||||
let_it_be(:runner_2) { create(:ci_runner, :instance, description: 'runner-2-blue', tag_list: ['blue']) }
|
||||
let_it_be(:runner_3) { create(:ci_runner, :instance, description: 'runner-red', tag_list: ['red']) }
|
||||
|
||||
before do
|
||||
visit admin_runners_path
|
||||
end
|
||||
|
||||
it 'shows tags suggestions' do
|
||||
visit admin_runners_path
|
||||
|
||||
open_filtered_search_suggestions('Tags')
|
||||
|
||||
page.within(search_bar_selector) do
|
||||
|
@ -367,23 +368,25 @@ RSpec.describe "Admin Runners" do
|
|||
end
|
||||
end
|
||||
|
||||
it 'shows correct runner when tag matches' do
|
||||
visit admin_runners_path
|
||||
it_behaves_like 'filters by tag' do
|
||||
let(:tag) { 'blue' }
|
||||
let(:found_runner) { runner_1.description }
|
||||
let(:missing_runner) { runner_3.description }
|
||||
end
|
||||
|
||||
expect(page).to have_content 'runner-blue'
|
||||
expect(page).to have_content 'runner-red'
|
||||
context 'when tag does not match' do
|
||||
before do
|
||||
input_filtered_search_filter_is_only('Tags', 'green')
|
||||
end
|
||||
|
||||
input_filtered_search_filter_is_only('Tags', 'blue')
|
||||
it_behaves_like 'shows no runners found'
|
||||
|
||||
expect(page).to have_content 'runner-blue'
|
||||
expect(page).not_to have_content 'runner-red'
|
||||
it 'shows no runner' do
|
||||
expect(page).not_to have_content 'runner-blue'
|
||||
end
|
||||
end
|
||||
|
||||
it 'shows correct runner when tag is selected and search term is entered' do
|
||||
create(:ci_runner, :instance, description: 'runner-2-blue', tag_list: ['blue'])
|
||||
|
||||
visit admin_runners_path
|
||||
|
||||
input_filtered_search_filter_is_only('Tags', 'blue')
|
||||
|
||||
expect(page).to have_content 'runner-blue'
|
||||
|
@ -396,19 +399,6 @@ RSpec.describe "Admin Runners" do
|
|||
expect(page).not_to have_content 'runner-blue'
|
||||
expect(page).not_to have_content 'runner-red'
|
||||
end
|
||||
|
||||
context 'when tag does not match' do
|
||||
before do
|
||||
visit admin_runners_path
|
||||
input_filtered_search_filter_is_only('Tags', 'green')
|
||||
end
|
||||
|
||||
it_behaves_like 'shows no runners found'
|
||||
|
||||
it 'shows no runner' do
|
||||
expect(page).not_to have_content 'runner-blue'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'sorts by last contact date' do
|
||||
|
|
|
@ -189,6 +189,21 @@ RSpec.describe "Group Runners" do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'filter by tag' do
|
||||
let!(:runner_1) { create(:ci_runner, :group, groups: [group], description: 'runner-blue', tag_list: ['blue']) }
|
||||
let!(:runner_2) { create(:ci_runner, :group, groups: [group], description: 'runner-red', tag_list: ['red']) }
|
||||
|
||||
before do
|
||||
visit group_runners_path(group)
|
||||
end
|
||||
|
||||
it_behaves_like 'filters by tag' do
|
||||
let(:tag) { 'blue' }
|
||||
let(:found_runner) { runner_1.description }
|
||||
let(:missing_runner) { runner_2.description }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Group runner show page", :js do
|
||||
|
|
|
@ -77,7 +77,7 @@ describe('TagToken', () => {
|
|||
const findToken = () => wrapper.findComponent(GlToken);
|
||||
const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
|
||||
mock.onGet(TAG_SUGGESTIONS_PATH, { params: { search: '' } }).reply(200, mockTags);
|
||||
|
@ -86,9 +86,6 @@ describe('TagToken', () => {
|
|||
.reply(200, mockTagsFiltered);
|
||||
|
||||
getRecentlyUsedSuggestions.mockReturnValue([]);
|
||||
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -97,11 +94,17 @@ describe('TagToken', () => {
|
|||
});
|
||||
|
||||
describe('when the tags token is displayed', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('requests tags suggestions', () => {
|
||||
expect(mock.history.get[0].params).toEqual({ search: '' });
|
||||
});
|
||||
|
||||
it('displays tags suggestions', () => {
|
||||
it('displays tags suggestions', async () => {
|
||||
await waitForPromises();
|
||||
|
||||
mockTags.forEach(({ name }, i) => {
|
||||
expect(findGlFilteredSearchSuggestions().at(i).text()).toBe(name);
|
||||
});
|
||||
|
@ -132,13 +135,13 @@ describe('TagToken', () => {
|
|||
});
|
||||
|
||||
describe('when the users filters suggestions', () => {
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
|
||||
findGlFilteredSearchToken().vm.$emit('input', { data: mockSearchTerm });
|
||||
});
|
||||
|
||||
it('requests filtered tags suggestions', async () => {
|
||||
await waitForPromises();
|
||||
|
||||
it('requests filtered tags suggestions', () => {
|
||||
expect(mock.history.get[1].params).toEqual({ search: mockSearchTerm });
|
||||
});
|
||||
|
||||
|
@ -166,7 +169,7 @@ describe('TagToken', () => {
|
|||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('error is shown', async () => {
|
||||
it('error is shown', () => {
|
||||
expect(createAlert).toHaveBeenCalledTimes(1);
|
||||
expect(createAlert).toHaveBeenCalledWith({ message: expect.any(String) });
|
||||
});
|
||||
|
@ -180,8 +183,26 @@ describe('TagToken', () => {
|
|||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('selected tag is displayed', async () => {
|
||||
it('selected tag is displayed', () => {
|
||||
expect(findToken().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when suggestions are disabled', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
config: {
|
||||
...mockTagTokenConfig,
|
||||
suggestionsDisabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('displays no suggestions', () => {
|
||||
expect(findGlFilteredSearchSuggestions()).toHaveLength(0);
|
||||
expect(mock.history.get).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -37,6 +37,7 @@ import {
|
|||
GROUP_TYPE,
|
||||
PARAM_KEY_PAUSED,
|
||||
PARAM_KEY_STATUS,
|
||||
PARAM_KEY_TAG,
|
||||
STATUS_ONLINE,
|
||||
STATUS_OFFLINE,
|
||||
STATUS_STALE,
|
||||
|
@ -269,6 +270,10 @@ describe('GroupRunnersApp', () => {
|
|||
type: PARAM_KEY_STATUS,
|
||||
options: expect.any(Array),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
type: PARAM_KEY_TAG,
|
||||
suggestionsDisabled: true,
|
||||
}),
|
||||
upgradeStatusTokenConfig,
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -146,6 +146,18 @@ RSpec.shared_examples 'pauses, resumes and deletes a runner' do
|
|||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'filters by tag' do
|
||||
it 'shows correct runner when tag matches' do
|
||||
expect(page).to have_content found_runner
|
||||
expect(page).to have_content missing_runner
|
||||
|
||||
input_filtered_search_filter_is_only('Tags', tag)
|
||||
|
||||
expect(page).to have_content found_runner
|
||||
expect(page).not_to have_content missing_runner
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'submits edit runner form' do
|
||||
it 'breadcrumb contains runner id and token' do
|
||||
page.within '[data-testid="breadcrumb-links"]' do
|
||||
|
|
Loading…
Reference in a new issue