Remove mercurial support

This commit is contained in:
Alan Rominger 2020-12-01 14:06:34 -05:00
parent 62be4defa2
commit 44e6e9344b
No known key found for this signature in database
GPG Key ID: C2D7EAAA12B63559
30 changed files with 45 additions and 165 deletions

View File

@ -2,6 +2,9 @@
This is a list of high-level changes for each release of AWX. A full list of commits can be found at `https://github.com/ansible/awx/releases/tag/<version>`.
## 16.0.0 (TBD)
- Removed support for Mercurial-based project updates - https://github.com/ansible/tower/issues/4727
## 15.0.1 (October 20, 2020)
- Added several optimizations to improve performance for a variety of high-load simultaneous job launch use cases https://github.com/ansible/awx/pull/8403
- Added the ability to source roles and collections from requirements.yaml files (not just requirements.yml) - https://github.com/ansible/awx/issues/4540
@ -88,7 +91,7 @@ This is a list of high-level changes for each release of AWX. A full list of com
- Fixed a bug that caused rsyslogd's configuration file to have world-readable file permissions, potentially leaking secrets (CVE-2020-10782)
## 12.0.0 (Jun 9, 2020)
- Removed memcached as a dependency of AWX (https://github.com/ansible/awx/pull/7240)
- Removed memcached as a dependency of AWX (https://github.com/ansible/awx/pull/7240)
- Moved to a single container image build instead of separate awx_web and awx_task images. The container image is just `awx` (https://github.com/ansible/awx/pull/7228)
- Official AWX container image builds now use a two-stage container build process that notably reduces the size of our published images (https://github.com/ansible/awx/pull/7017)
- Removed support for HipChat notifications ([EoL announcement](https://www.atlassian.com/partnerships/slack/faq#faq-98b17ca3-247f-423b-9a78-70a91681eff0)); all previously-created HipChat notification templates will be deleted due to this removal.

View File

@ -640,7 +640,7 @@ class EmptySerializer(serializers.Serializer):
class UnifiedJobTemplateSerializer(BaseSerializer):
# As a base serializer, the capabilities prefetch is not used directly,
# As a base serializer, the capabilities prefetch is not used directly,
# instead they are derived from the Workflow Job Template Serializer and the Job Template Serializer, respectively.
capabilities_prefetch = []
@ -1748,7 +1748,7 @@ class HostSerializer(BaseSerializerWithVariables):
attrs['variables'] = json.dumps(vars_dict)
if Group.objects.filter(name=name, inventory=inventory).exists():
raise serializers.ValidationError(_('A Group with that name already exists.'))
return super(HostSerializer, self).validate(attrs)
def to_representation(self, obj):
@ -3945,12 +3945,12 @@ class ProjectUpdateEventSerializer(JobEventSerializer):
return UriCleaner.remove_sensitive(obj.stdout)
def get_event_data(self, obj):
# the project update playbook uses the git, hg, or svn modules
# the project update playbook uses the git or svn modules
# to clone repositories, and those modules are prone to printing
# raw SCM URLs in their stdout (which *could* contain passwords)
# attempt to detect and filter HTTP basic auth passwords in the stdout
# of these types of events
if obj.event_data.get('task_action') in ('git', 'hg', 'svn'):
if obj.event_data.get('task_action') in ('git', 'svn'):
try:
return json.loads(
UriCleaner.remove_sensitive(

View File

@ -242,8 +242,6 @@ class DashboardView(APIView):
git_failed_projects = git_projects.filter(last_job_failed=True)
svn_projects = user_projects.filter(scm_type='svn')
svn_failed_projects = svn_projects.filter(last_job_failed=True)
hg_projects = user_projects.filter(scm_type='hg')
hg_failed_projects = hg_projects.filter(last_job_failed=True)
archive_projects = user_projects.filter(scm_type='archive')
archive_failed_projects = archive_projects.filter(last_job_failed=True)
data['scm_types'] = {}
@ -257,11 +255,6 @@ class DashboardView(APIView):
'failures_url': reverse('api:project_list', request=request) + "?scm_type=svn&last_job_failed=True",
'total': svn_projects.count(),
'failed': svn_failed_projects.count()}
data['scm_types']['hg'] = {'url': reverse('api:project_list', request=request) + "?scm_type=hg",
'label': 'Mercurial',
'failures_url': reverse('api:project_list', request=request) + "?scm_type=hg&last_job_failed=True",
'total': hg_projects.count(),
'failed': hg_failed_projects.count()}
data['scm_types']['archive'] = {'url': reverse('api:project_list', request=request) + "?scm_type=archive",
'label': 'Remote Archive',
'failures_url': reverse('api:project_list', request=request) + "?scm_type=archive&last_job_failed=True",

View File

@ -68,7 +68,7 @@ def register(key, version, description=None, format='json', expensive=False):
@register('projects_by_scm_type', 1)
def projects_by_scm_type():
return {'git': 5, 'svn': 1, 'hg': 0}
return {'git': 5, 'svn': 1}
"""
def decorate(f):
@ -102,7 +102,7 @@ def gather(dest=None, module=None, subset = None, since = None, until = now(), c
last_run = since or settings.AUTOMATION_ANALYTICS_LAST_GATHER or (now() - timedelta(weeks=4))
logger.debug("Last analytics run was: {}".format(settings.AUTOMATION_ANALYTICS_LAST_GATHER))
if _valid_license() is False:
logger.exception("Invalid License provided, or No License Provided")
return None

View File

@ -149,7 +149,6 @@ class IsolatedManager(object):
# don't rsync source control metadata (it can be huge!)
'- /project/.git',
'- /project/.svn',
'- /project/.hg',
# don't rsync job events that are in the process of being written
'- /artifacts/job_events/*-partial.json.tmp',
# don't rsync the ssh_key FIFO

View File

@ -0,0 +1,23 @@
# Generated by Django 2.2.16 on 2020-12-01 18:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0122_really_remove_cloudforms_inventory'),
]
operations = [
migrations.AlterField(
model_name='project',
name='scm_type',
field=models.CharField(blank=True, choices=[('', 'Manual'), ('git', 'Git'), ('svn', 'Subversion'), ('insights', 'Red Hat Insights'), ('archive', 'Remote Archive')], default='', help_text='Specifies the source control system used to store the project.', max_length=8, verbose_name='SCM Type'),
),
migrations.AlterField(
model_name='projectupdate',
name='scm_type',
field=models.CharField(blank=True, choices=[('', 'Manual'), ('git', 'Git'), ('svn', 'Subversion'), ('insights', 'Red Hat Insights'), ('archive', 'Remote Archive')], default='', help_text='Specifies the source control system used to store the project.', max_length=8, verbose_name='SCM Type'),
),
]

View File

@ -52,7 +52,6 @@ class ProjectOptions(models.Model):
SCM_TYPE_CHOICES = [
('', _('Manual')),
('git', _('Git')),
('hg', _('Mercurial')),
('svn', _('Subversion')),
('insights', _('Red Hat Insights')),
('archive', _('Remote Archive')),

View File

@ -1260,7 +1260,7 @@ class BaseTask(object):
# so it *should* have a negligible performance impact
task = event_data.get('event_data', {}).get('task_action')
try:
if task in ('git', 'hg', 'svn'):
if task in ('git', 'svn'):
event_data_json = json.dumps(event_data)
event_data_json = UriCleaner.remove_sensitive(event_data_json)
event_data = json.loads(event_data_json)
@ -2154,7 +2154,7 @@ class RunProjectUpdate(BaseTask):
elif not scm_branch:
raise RuntimeError('Could not determine a revision to run from project.')
elif not scm_branch:
scm_branch = {'hg': 'tip'}.get(project_update.scm_type, 'HEAD')
scm_branch = 'HEAD'
galaxy_creds_are_defined = (
project_update.project.organization and

View File

@ -1909,19 +1909,16 @@ class TestProjectUpdateCredentials(TestJobExecution):
parametrize = {
'test_username_and_password_auth': [
dict(scm_type='git'),
dict(scm_type='hg'),
dict(scm_type='svn'),
dict(scm_type='archive'),
],
'test_ssh_key_auth': [
dict(scm_type='git'),
dict(scm_type='hg'),
dict(scm_type='svn'),
dict(scm_type='archive'),
],
'test_awx_task_env': [
dict(scm_type='git'),
dict(scm_type='hg'),
dict(scm_type='svn'),
dict(scm_type='archive'),
]

View File

@ -222,9 +222,8 @@ def update_scm_url(scm_type, url, username=True, password=True,
'''
# Handle all of the URL formats supported by the SCM systems:
# git: https://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS
# hg: http://www.selenic.com/mercurial/hg.1.html#url-paths
# svn: http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.advanced.reposurls
if scm_type not in ('git', 'hg', 'svn', 'insights', 'archive'):
if scm_type not in ('git', 'svn', 'insights', 'archive'):
raise ValueError(_('Unsupported SCM type "%s"') % str(scm_type))
if not url.strip():
return ''
@ -256,8 +255,8 @@ def update_scm_url(scm_type, url, username=True, password=True,
# SCP style before passed to git module.
parts = urllib.parse.urlsplit('git+ssh://%s' % modified_url)
# Handle local paths specified without file scheme (e.g. /path/to/foo).
# Only supported by git and hg.
elif scm_type in ('git', 'hg'):
# Only supported by git.
elif scm_type == 'git':
if not url.startswith('/'):
parts = urllib.parse.urlsplit('file:///%s' % url)
else:
@ -268,7 +267,6 @@ def update_scm_url(scm_type, url, username=True, password=True,
# Validate that scheme is valid for given scm_type.
scm_type_schemes = {
'git': ('ssh', 'git', 'git+ssh', 'http', 'https', 'ftp', 'ftps', 'file'),
'hg': ('http', 'https', 'ssh', 'file'),
'svn': ('http', 'https', 'svn', 'svn+ssh', 'file'),
'insights': ('http', 'https'),
'archive': ('http', 'https'),
@ -300,12 +298,6 @@ def update_scm_url(scm_type, url, username=True, password=True,
if scm_type == 'git' and parts.scheme.endswith('ssh') and parts.hostname in special_git_hosts and netloc_password:
#raise ValueError('Password not allowed for SSH access to %s.' % parts.hostname)
netloc_password = ''
special_hg_hosts = ('bitbucket.org', 'altssh.bitbucket.org')
if scm_type == 'hg' and parts.scheme == 'ssh' and parts.hostname in special_hg_hosts and netloc_username != 'hg':
raise ValueError(_('Username must be "hg" for SSH access to %s.') % parts.hostname)
if scm_type == 'hg' and parts.scheme == 'ssh' and netloc_password:
#raise ValueError('Password not supported for SSH with Mercurial.')
netloc_password = ''
if netloc_username and parts.scheme != 'file' and scm_type not in ("insights", "archive"):
netloc = u':'.join([urllib.parse.quote(x,safe='') for x in (netloc_username, netloc_password) if x])

View File

@ -1,15 +0,0 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.plugins.action import ActionBase
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
self._supports_check_mode = False
result = super(ActionModule, self).run(tmp, task_vars)
result['changed'] = result['failed'] = False
result['msg'] = ''
self._display.deprecated("Mercurial support is deprecated")
return result

View File

@ -48,12 +48,6 @@
tags:
- update_git
- block:
- name: include hg tasks
include_tasks: project_update_hg_tasks.yml
tags:
- update_hg
- block:
- name: update project using svn
subversion:
@ -150,7 +144,6 @@
msg: "Repository Version {{ scm_version }}"
tags:
- update_git
- update_hg
- update_svn
- update_insights
- update_archive

View File

@ -1,20 +0,0 @@
---
- name: Mercurial support is deprecated.
hg_deprecation:
- name: update project using hg
hg:
dest: "{{project_path|quote}}"
repo: "{{scm_url|quote}}"
revision: "{{scm_branch|quote}}"
force: "{{scm_clean}}"
register: hg_result
- name: Set the hg repository version
set_fact:
scm_version: "{{ hg_result['after'] }}"
when: "'after' in hg_result"
- name: parse hg version string properly
set_fact:
scm_version: "{{scm_version|regex_replace('^([A-Za-z0-9]+).*$', '\\1')}}"

View File

@ -175,13 +175,6 @@ TEST_GIT_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com.git'
TEST_GIT_PRIVATE_HTTPS = 'https://github.com/ansible/product-docs.git'
TEST_GIT_PRIVATE_SSH = 'git@github.com:ansible/product-docs.git'
TEST_HG_USERNAME = ''
TEST_HG_PASSWORD = ''
TEST_HG_KEY_DATA = TEST_SSH_KEY_DATA
TEST_HG_PUBLIC_HTTPS = 'https://bitbucket.org/cchurch/django-hotrunner'
TEST_HG_PRIVATE_HTTPS = ''
TEST_HG_PRIVATE_SSH = ''
TEST_SVN_USERNAME = ''
TEST_SVN_PASSWORD = ''
TEST_SVN_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com'

View File

@ -38,7 +38,7 @@ if is_testing(sys.argv):
},
}
}
# AMQP configuration.
BROKER_URL = 'amqp://guest:guest@localhost:5672'
@ -146,13 +146,6 @@ TEST_GIT_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com.git'
TEST_GIT_PRIVATE_HTTPS = 'https://github.com/ansible/product-docs.git'
TEST_GIT_PRIVATE_SSH = 'git@github.com:ansible/product-docs.git'
TEST_HG_USERNAME = ''
TEST_HG_PASSWORD = ''
TEST_HG_KEY_DATA = TEST_SSH_KEY_DATA
TEST_HG_PUBLIC_HTTPS = 'https://bitbucket.org/cchurch/django-hotrunner'
TEST_HG_PRIVATE_HTTPS = ''
TEST_HG_PRIVATE_SSH = ''
TEST_SVN_USERNAME = ''
TEST_SVN_PASSWORD = ''
TEST_SVN_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com'

View File

@ -108,7 +108,6 @@ function ProjectLookup({
options: [
[``, i18n._(t`Manual`)],
[`git`, i18n._(t`Git`)],
[`hg`, i18n._(t`Mercurial`)],
[`svn`, i18n._(t`Subversion`)],
[`archive`, i18n._(t`Remote Archive`)],
[`insights`, i18n._(t`Red Hat Insights`)],

View File

@ -87,7 +87,6 @@ export default function getResourceAccessConfig(i18n) {
options: [
[``, i18n._(t`Manual`)],
[`git`, i18n._(t`Git`)],
[`hg`, i18n._(t`Mercurial`)],
[`svn`, i18n._(t`Subversion`)],
[`archive`, i18n._(t`Remote Archive`)],
[`insights`, i18n._(t`Red Hat Insights`)],
@ -157,7 +156,6 @@ export default function getResourceAccessConfig(i18n) {
options: [
[``, i18n._(t`Manual`)],
[`git`, i18n._(t`Git`)],
[`hg`, i18n._(t`Mercurial`)],
[`svn`, i18n._(t`Subversion`)],
[`archive`, i18n._(t`Remote Archive`)],
[`insights`, i18n._(t`Red Hat Insights`)],

View File

@ -35,7 +35,6 @@ describe('<ProjectAdd />', () => {
choices: [
['', 'Manual'],
['git', 'Git'],
['hg', 'Mercurial'],
['svn', 'Subversion'],
['archive', 'Remote Archive'],
['insights', 'Red Hat Insights'],

View File

@ -47,7 +47,6 @@ describe('<ProjectEdit />', () => {
choices: [
['', 'Manual'],
['git', 'Git'],
['hg', 'Mercurial'],
['svn', 'Subversion'],
['archive', 'Remote Archive'],
['insights', 'Red Hat Insights'],

View File

@ -140,7 +140,6 @@ function ProjectList({ i18n }) {
options: [
[``, i18n._(t`Manual`)],
[`git`, i18n._(t`Git`)],
[`hg`, i18n._(t`Mercurial`)],
[`svn`, i18n._(t`Subversion`)],
[`archive`, i18n._(t`Remote Archive`)],
[`insights`, i18n._(t`Red Hat Insights`)],

View File

@ -21,7 +21,6 @@ import {
import Popover from '../../../components/Popover';
import {
GitSubForm,
HgSubForm,
SvnSubForm,
ArchiveSubForm,
InsightsSubForm,
@ -237,13 +236,6 @@ function ProjectFormFields({
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
hg: (
<HgSubForm
credential={credentials.scm}
onCredentialSelection={handleCredentialSelection}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
svn: (
<SvnSubForm
credential={credentials.scm}

View File

@ -45,7 +45,6 @@ describe('<ProjectForm />', () => {
choices: [
['', 'Manual'],
['git', 'Git'],
['hg', 'Mercurial'],
['svn', 'Subversion'],
['archive', 'Remote Archive'],
['insights', 'Red Hat Insights'],
@ -295,10 +294,6 @@ describe('<ProjectForm />', () => {
const scmTypeSelect = wrapper.find(
'FormGroup[label="Source Control Credential Type"] FormSelect'
);
await act(async () => {
scmTypeSelect.invoke('onChange')('hg', { target: { name: 'Mercurial' } });
});
wrapper.update();
await act(async () => {
wrapper
.find('FormGroup[label="Source Control URL"] input')

View File

@ -1,48 +0,0 @@
import 'styled-components/macro';
import React from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
UrlFormField,
BranchFormField,
ScmCredentialFormField,
ScmTypeOptions,
} from './SharedFields';
const HgSubForm = ({
i18n,
credential,
onCredentialSelection,
scmUpdateOnLaunch,
}) => (
<>
<UrlFormField
i18n={i18n}
tooltip={
<span>
{i18n._(t`Example URLs for Mercurial Source Control include:`)}
<ul css={{ margin: '10px 0 10px 20px' }}>
<li>https://bitbucket.org/username/project</li>
<li>ssh://hg@bitbucket.org/username/project</li>
<li>ssh://server.example.com/path</li>
</ul>
{i18n._(t`Note: Mercurial does not support password authentication
for SSH. Do not put the username and key in the URL. If using
Bitbucket and SSH, do not supply your Bitbucket username.
`)}
</span>
}
/>
<BranchFormField
i18n={i18n}
label={i18n._(t`Source Control Branch/Tag/Revision`)}
/>
<ScmCredentialFormField
credential={credential}
onCredentialSelection={onCredentialSelection}
/>
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>
);
export default withI18n()(HgSubForm);

View File

@ -1,5 +1,4 @@
export { default as GitSubForm } from './GitSubForm';
export { default as HgSubForm } from './HgSubForm';
export { default as InsightsSubForm } from './InsightsSubForm';
export { default as ManualSubForm } from './ManualSubForm';
export { default as SvnSubForm } from './SvnSubForm';

View File

@ -88,7 +88,6 @@ function ProjectsList({ i18n, nodeResource, onUpdateNodeResource }) {
options: [
[``, i18n._(t`Manual`)],
[`git`, i18n._(t`Git`)],
[`hg`, i18n._(t`Mercurial`)],
[`svn`, i18n._(t`Subversion`)],
[`archive`, i18n._(t`Remote Archive`)],
[`insights`, i18n._(t`Red Hat Insights`)],

View File

@ -153,7 +153,7 @@ export const Project = shape({
created: string,
name: string.isRequired,
description: string,
scm_type: oneOf(['', 'git', 'hg', 'svn', 'archive', 'insights']),
scm_type: oneOf(['', 'git', 'svn', 'archive', 'insights']),
scm_url: string,
scm_branch: string,
scm_refspec: string,

View File

@ -34,7 +34,7 @@ options:
scm_type:
description:
- Type of SCM resource.
choices: ["manual", "git", "hg", "svn", "insights"]
choices: ["manual", "git", "svn", "insights"]
default: "manual"
type: str
scm_url:
@ -186,7 +186,7 @@ def main():
argument_spec = dict(
name=dict(required=True),
description=dict(),
scm_type=dict(choices=['manual', 'git', 'hg', 'svn', 'insights'], default='manual'),
scm_type=dict(choices=['manual', 'git', 'svn', 'insights'], default='manual'),
scm_url=dict(),
local_path=dict(),
scm_branch=dict(default=''),

View File

@ -304,7 +304,7 @@ When verifying acceptance, we should ensure that the following statements are tr
- Break the link between instances such that it forms two or more groups where Group A and Group B can't communicate but all instances can communicate with the database.
* Crucially, when network partitioning is resolved, all instances should recover into a consistent state.
* Upgrade Testing - verify behavior before and after are the same for the end user.
* Project Updates should be thoroughly tested for all SCM types (`git`, `svn`, `hg`) and for manual projects.
* Project Updates should be thoroughly tested for all SCM types (`git`, `svn`, `archive`) and for manual projects.
* Setting up instance groups in two scenarios:
a) instances are shared between groups
b) instances are isolated to particular groups

View File

@ -16,8 +16,8 @@ of the most notable ones are:
### Projects
Projects represent a collection of Ansible playbooks. Most AWX users create
Projects that import periodically from source control systems (such as git,
mercurial, or subversion repositories). This import is accomplished via an
Projects that import periodically from source control systems (such as git
or subversion repositories). This import is accomplished via an
Ansible playbook included with AWX (which makes use of the various source
control management modules in Ansible).

View File

@ -125,7 +125,6 @@ RUN dnf -y update && \
glibc-langpack-en \
krb5-workstation \
libcgroup-tools \
mercurial \
nginx \
@postgresql:10 \
python3-devel \