Commit 8ad1afad authored by Mark Florian's avatar Mark Florian

Merge branch...

Merge branch '232794-include-the-installation-instructions-for-composer-dependencies-in-the-package-registry-ui' into 'master'

Add installation instructions for Composer

See merge request gitlab-org/gitlab!38779
parents 27b63550 ec8c9bdf
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import CodeInstruction from './code_instruction.vue';
import { TrackingActions } from '../constants';
import { mapGetters, mapState } from 'vuex';
export default {
name: 'ComposerInstallation',
components: {
CodeInstruction,
GlLink,
GlSprintf,
},
computed: {
...mapState(['composerHelpPath']),
...mapGetters(['composerRegistryInclude', 'composerPackageInclude']),
},
i18n: {
registryInclude: s__('PackageRegistry|composer.json registry include'),
copyRegistryInclude: s__('PackageRegistry|Copy registry include'),
packageInclude: s__('PackageRegistry|composer.json require package include'),
copyPackageInclude: s__('PackageRegistry|Copy require package include'),
infoLine: s__(
'PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}',
),
},
trackingActions: { ...TrackingActions },
};
</script>
<template>
<div>
<p class="gl-mt-3 gl-font-weight-bold" data-testid="registry-include-title">
{{ $options.i18n.registryInclude }}
</p>
<code-instruction
:instruction="composerRegistryInclude"
:copy-text="$options.i18n.copyRegistryInclude"
:tracking-action="$options.trackingActions.COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND"
/>
<p class="gl-mt-3 gl-font-weight-bold" data-testid="package-include-title">
{{ $options.i18n.packageInclude }}
</p>
<code-instruction
:instruction="composerPackageInclude"
:copy-text="$options.i18n.copyPackageInclude"
:tracking-action="$options.trackingActions.COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND"
/>
<span data-testid="help-text">
<gl-sprintf :message="$options.i18n.infoLine">
<template #link="{ content }">
<gl-link :href="composerHelpPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
</div>
</template>
...@@ -4,6 +4,7 @@ import MavenInstallation from './maven_installation.vue'; ...@@ -4,6 +4,7 @@ import MavenInstallation from './maven_installation.vue';
import NpmInstallation from './npm_installation.vue'; import NpmInstallation from './npm_installation.vue';
import NugetInstallation from './nuget_installation.vue'; import NugetInstallation from './nuget_installation.vue';
import PypiInstallation from './pypi_installation.vue'; import PypiInstallation from './pypi_installation.vue';
import ComposerInstallation from './composer_installation.vue';
import { PackageType } from '../../shared/constants'; import { PackageType } from '../../shared/constants';
export default { export default {
...@@ -14,6 +15,7 @@ export default { ...@@ -14,6 +15,7 @@ export default {
[PackageType.NPM]: NpmInstallation, [PackageType.NPM]: NpmInstallation,
[PackageType.NUGET]: NugetInstallation, [PackageType.NUGET]: NugetInstallation,
[PackageType.PYPI]: PypiInstallation, [PackageType.PYPI]: PypiInstallation,
[PackageType.COMPOSER]: ComposerInstallation,
}, },
props: { props: {
packageEntity: { packageEntity: {
......
...@@ -7,6 +7,7 @@ export const TrackingLabels = { ...@@ -7,6 +7,7 @@ export const TrackingLabels = {
NPM_INSTALLATION: 'npm_installation', NPM_INSTALLATION: 'npm_installation',
NUGET_INSTALLATION: 'nuget_installation', NUGET_INSTALLATION: 'nuget_installation',
PYPI_INSTALLATION: 'pypi_installation', PYPI_INSTALLATION: 'pypi_installation',
COMPOSER_INSTALLATION: 'composer_installation',
}; };
export const TrackingActions = { export const TrackingActions = {
...@@ -31,6 +32,9 @@ export const TrackingActions = { ...@@ -31,6 +32,9 @@ export const TrackingActions = {
COPY_PIP_INSTALL_COMMAND: 'copy_pip_install_command', COPY_PIP_INSTALL_COMMAND: 'copy_pip_install_command',
COPY_PYPI_SETUP_COMMAND: 'copy_pypi_setup_command', COPY_PYPI_SETUP_COMMAND: 'copy_pypi_setup_command',
COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND: 'copy_composer_registry_include_command',
COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND: 'copy_composer_package_include_command',
}; };
export const NpmManager = { export const NpmManager = {
......
...@@ -104,3 +104,12 @@ export const pypiSetupCommand = ({ pypiSetupPath }) => `[gitlab] ...@@ -104,3 +104,12 @@ export const pypiSetupCommand = ({ pypiSetupPath }) => `[gitlab]
repository = ${pypiSetupPath} repository = ${pypiSetupPath}
username = __token__ username = __token__
password = <your personal access token>`; password = <your personal access token>`;
export const composerRegistryInclude = ({ composerPath }) => {
const base = { type: 'composer', url: composerPath };
return JSON.stringify(base);
};
export const composerPackageInclude = ({ packageEntity }) => {
const base = { package_name: packageEntity.name };
return JSON.stringify(base);
};
...@@ -30,6 +30,10 @@ module PackagesHelper ...@@ -30,6 +30,10 @@ module PackagesHelper
full_url.sub!('://', '://__token__:<your_personal_token>@') full_url.sub!('://', '://__token__:<your_personal_token>@')
end end
def composer_registry_url(group_id)
expose_url(api_v4_group___packages_composer_packages_path(id: group_id, format: '.json'))
end
def packages_coming_soon_enabled?(resource) def packages_coming_soon_enabled?(resource)
::Feature.enabled?(:packages_coming_soon, resource) && ::Gitlab.dev_env_or_com? ::Feature.enabled?(:packages_coming_soon, resource) && ::Gitlab.dev_env_or_com?
end end
......
...@@ -20,4 +20,6 @@ ...@@ -20,4 +20,6 @@
pypi_path: pypi_registry_url(@project.id), pypi_path: pypi_registry_url(@project.id),
pypi_setup_path: package_registry_project_url(@project.id, :pypi), pypi_setup_path: package_registry_project_url(@project.id, :pypi),
pypi_help_path: help_page_path('user/packages/pypi_repository/index'), pypi_help_path: help_page_path('user/packages/pypi_repository/index'),
composer_path: composer_registry_url(@project&.group&.id),
composer_help_path: help_page_path('user/packages/composer_repository/index'),
project_name: @project.name} } project_name: @project.name} }
---
title: Add installation instructions for Composer
merge_request: 38779
author:
type: changed
...@@ -17125,6 +17125,12 @@ msgstr "" ...@@ -17125,6 +17125,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command" msgid "PackageRegistry|Copy npm setup command"
msgstr "" msgstr ""
msgid "PackageRegistry|Copy registry include"
msgstr ""
msgid "PackageRegistry|Copy require package include"
msgstr ""
msgid "PackageRegistry|Copy yarn command" msgid "PackageRegistry|Copy yarn command"
msgstr "" msgstr ""
...@@ -17140,6 +17146,9 @@ msgstr "" ...@@ -17140,6 +17146,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name" msgid "PackageRegistry|Filter by name"
msgstr "" msgstr ""
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}." msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "" msgstr ""
...@@ -17260,6 +17269,12 @@ msgstr "" ...@@ -17260,6 +17269,12 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more." msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "" msgstr ""
msgid "PackageRegistry|composer.json registry include"
msgstr ""
msgid "PackageRegistry|composer.json require package include"
msgstr ""
msgid "PackageRegistry|npm" msgid "PackageRegistry|npm"
msgstr "" msgstr ""
......
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlSprintf, GlLink } from '@gitlab/ui';
import ComposerInstallation from '~/packages/details/components/composer_installation.vue';
import CodeInstructions from '~/packages/details/components/code_instruction.vue';
import { TrackingActions } from '~/packages/details/constants';
import { registryUrl as composerHelpPath } from 'jest/packages/details/mock_data';
import { composerPackage as packageEntity } from 'jest/packages/mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('ComposerInstallation', () => {
let wrapper;
const composerRegistryIncludeStr = 'foo/registry';
const composerPackageIncludeStr = 'foo/package';
const store = new Vuex.Store({
state: {
packageEntity,
composerHelpPath,
},
getters: {
composerRegistryInclude: () => composerRegistryIncludeStr,
composerPackageInclude: () => composerPackageIncludeStr,
},
});
const findCodeInstructions = () => wrapper.findAll(CodeInstructions);
const findRegistryIncludeTitle = () => wrapper.find('[data-testid="registry-include-title"]');
const findPackageIncludeTitle = () => wrapper.find('[data-testid="package-include-title"]');
const findHelpText = () => wrapper.find('[data-testid="help-text"]');
const findHelpLink = () => wrapper.find(GlLink);
function createComponent() {
wrapper = shallowMount(ComposerInstallation, {
localVue,
store,
stubs: {
GlSprintf,
},
});
}
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
describe('registry include command', () => {
it('uses code_instructions', () => {
const registryIncludeCommand = findCodeInstructions().at(0);
expect(registryIncludeCommand.exists()).toBe(true);
expect(registryIncludeCommand.props()).toMatchObject({
instruction: composerRegistryIncludeStr,
copyText: 'Copy registry include',
trackingAction: TrackingActions.COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND,
});
});
it('has the correct title', () => {
expect(findRegistryIncludeTitle().text()).toBe('composer.json registry include');
});
});
describe('package include command', () => {
it('uses code_instructions', () => {
const registryIncludeCommand = findCodeInstructions().at(1);
expect(registryIncludeCommand.exists()).toBe(true);
expect(registryIncludeCommand.props()).toMatchObject({
instruction: composerPackageIncludeStr,
copyText: 'Copy require package include',
trackingAction: TrackingActions.COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND,
});
});
it('has the correct title', () => {
expect(findPackageIncludeTitle().text()).toBe('composer.json require package include');
});
it('has the correct help text', () => {
expect(findHelpText().text()).toBe(
'For more information on Composer packages in GitLab, see the documentation.',
);
expect(findHelpLink().attributes()).toMatchObject({
href: composerHelpPath,
target: '_blank',
});
});
});
});
...@@ -6,8 +6,16 @@ import MavenInstallation from '~/packages/details/components/maven_installation. ...@@ -6,8 +6,16 @@ import MavenInstallation from '~/packages/details/components/maven_installation.
import ConanInstallation from '~/packages/details/components/conan_installation.vue'; import ConanInstallation from '~/packages/details/components/conan_installation.vue';
import NugetInstallation from '~/packages/details/components/nuget_installation.vue'; import NugetInstallation from '~/packages/details/components/nuget_installation.vue';
import PypiInstallation from '~/packages/details/components/pypi_installation.vue'; import PypiInstallation from '~/packages/details/components/pypi_installation.vue';
import ComposerInstallation from '~/packages/details/components/composer_installation.vue';
import { conanPackage, mavenPackage, npmPackage, nugetPackage, pypiPackage } from '../../mock_data'; import {
conanPackage,
mavenPackage,
npmPackage,
nugetPackage,
pypiPackage,
composerPackage,
} from '../../mock_data';
describe('InstallationCommands', () => { describe('InstallationCommands', () => {
let wrapper; let wrapper;
...@@ -23,6 +31,7 @@ describe('InstallationCommands', () => { ...@@ -23,6 +31,7 @@ describe('InstallationCommands', () => {
const conanInstallation = () => wrapper.find(ConanInstallation); const conanInstallation = () => wrapper.find(ConanInstallation);
const nugetInstallation = () => wrapper.find(NugetInstallation); const nugetInstallation = () => wrapper.find(NugetInstallation);
const pypiInstallation = () => wrapper.find(PypiInstallation); const pypiInstallation = () => wrapper.find(PypiInstallation);
const composerInstallation = () => wrapper.find(ComposerInstallation);
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
...@@ -36,6 +45,7 @@ describe('InstallationCommands', () => { ...@@ -36,6 +45,7 @@ describe('InstallationCommands', () => {
${npmPackage} | ${npmInstallation} ${npmPackage} | ${npmInstallation}
${nugetPackage} | ${nugetInstallation} ${nugetPackage} | ${nugetInstallation}
${pypiPackage} | ${pypiInstallation} ${pypiPackage} | ${pypiInstallation}
${composerPackage} | ${composerInstallation}
`('renders', ({ packageEntity, selector }) => { `('renders', ({ packageEntity, selector }) => {
it(`${packageEntity.package_type} instructions exist`, () => { it(`${packageEntity.package_type} instructions exist`, () => {
createComponent({ packageEntity }); createComponent({ packageEntity });
......
...@@ -44,6 +44,14 @@ RSpec.describe PackagesHelper do ...@@ -44,6 +44,14 @@ RSpec.describe PackagesHelper do
end end
end end
describe 'composer_registry_url' do
it 'return the composer registry url' do
url = helper.composer_registry_url(1)
expect(url).to eq("#{base_url}group/1/-/packages/composer/packages.json")
end
end
describe 'packages_coming_soon_enabled?' do describe 'packages_coming_soon_enabled?' do
it 'returns false when the feature flag is disabled' do it 'returns false when the feature flag is disabled' do
stub_feature_flags(packages_coming_soon: false) stub_feature_flags(packages_coming_soon: false)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment