-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow JT specification and prompting for project branch #4265
Allow JT specification and prompting for project branch #4265
Conversation
Merge Failed. This change or one of its cross-repo dependencies was unable to be automatically merged with the current state of its repository. Please rebase the change and upload a new patchset. |
ffe2c31
to
15418a7
Compare
15418a7
to
20867a3
Compare
Can you explain this more?
|
Using example: https://github.com/ansible/ansible/branches Steps:
This is because we run against the revision of the last "check"-type project update, which has its revision stored. Prompted, non-default branches, do not have their revision saved. We can change that, but a lot of question need to be answered. This behavior both was the least invasive, and closest to the requirements discussed in planning. I wanted to give pushback on this, but I'm happy with it now. While it's surprising that the default branch behaves differently from the non-default branch, it would also be surprising that different values of I might take some of this and put it in the docs folder, that had slipped my mind so-far. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot going on in tasks.py
here... I might want you to annotate what's going on and what you are working towards here, especially since it's going to affect project syncing overall.
awx/api/serializers.py
Outdated
if 'allow_override' in attrs and self.instance: | ||
if attrs['allow_override'] != self.instance: | ||
raise serializers.ValidationError({ | ||
'allow_override': _('Branch override behavior of a project cannot be changed after creation.')}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? Even if we know why we need to be able to tell people why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me recap the reason that this was added, say someone does this:
- make project with
allow_override
being true - makes JT with a non-blank
scm_branch
- changes project
allow_override
field back to False
Now the user has a JT that specifies a branch that we cannot apply.
Providing an outline of this case is far too much wording to put in an error message, but I agree the UI should at least show the error message from the API. Or hide it when in edit mode.
Also, this is more complicated than the other "prompts" related rejections of fields. If a JT's field is rejected because the project is configured to not allow it, we currently have no mechanism or precedent for dealing with that. We have no way of letting the user know that's broken without a lot of novel UI work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After more discussions, I agree the API side of this can be made smoother for the user interaction.
It would be fairly easy to combine a check with this, something like JobTemplate.objects.filter(project=obj).exclude(scm_branch="").exists()
, and then if both this condition is satisfied, and the allow_override
value changes from its prior value, then we could give a more specific error message:
Branch override behavior of this project is currently relied on by one or more existing job templates.
Then if there are no such JTs, we can just allow the PATCH/PUT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to @kdelee's view of things and your solution seems to be a step in the right direction @AlanCoding , it seems allowing the change makes more sense for the end user -- it would also make it easier if the dependent templates could be listed, though I'm unsure of performance impact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would also make it easier if the dependent templates could be listed
That's possible, but depends on how.
If all you're suggesting is a list of names or primary keys in the error message, then sure. That is super easy, and IMO no performance impact that matters. But this will not be linked.
Giving primary keys would be the most concise. If the message is too long, it will overflow the popup box, because error messages are intended to be concise. But if I give primary keys, I worry that someone will say that's a bad UX. But I think handling any special UI cases here is going way overboard for a corner case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AlanCoding I see the issue. How about something like a warning that existing job templates use branch override behavior, and offer a confirm button that would revert them if the person really doesn't care? If that's a lot to handle and offers chaos, then just the warning would be good though.
@@ -2701,7 +2706,7 @@ def get_summary_fields(self, obj): | |||
class JobOptionsSerializer(LabelsListMixin, BaseSerializer): | |||
|
|||
class Meta: | |||
fields = ('*', 'job_type', 'inventory', 'project', 'playbook', | |||
fields = ('*', 'job_type', 'inventory', 'project', 'playbook', 'scm_branch', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be consistent... it's scm_revision
elsewhere, which is more appropriate... it's more than just branch
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JobSerializer
has both fields scm_branch
and scm_revision
. The field name scm_branch
was borrowed from the Project
model.
The field scm_revision
is the SHA1 hash or technical specifier of the commit that a job is ran against (like "r49" for subversion). This serves the purpose of audibility in AWX / Tower so that someone can look back in time and be sure they can recover the exact version of the playbook that was ran.
scm_branch
is given by a user at some point. It can be several things, and the Ansible git module goes through fallback logic where it checks if it is (1) a branch (2) a tag (3) assume it's a commit, and possibly error. The fallback logic for evaluating an scm_branch here is modeled after their process.
@@ -396,7 +418,7 @@ def _accept_or_ignore_job_kwargs(self, **kwargs): | |||
# Not considered an error for manual launch, to support old | |||
# behavior of putting them in ignored_fields and launching anyway | |||
if 'prompts' not in exclude_errors: | |||
errors_dict[field_name] = _('Field is not configured to prompt on launch.').format(field_name=field_name) | |||
errors_dict[field_name] = _('Field is not configured to prompt on launch.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops.
@@ -41,6 +43,10 @@ | |||
# Django-CRUM | |||
from crum import impersonate | |||
|
|||
# GitPython | |||
import git |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I may need some help understanding what is going on in this file.... is it just Runner usage cleanup?
awx/main/tasks.py
Outdated
except (ValueError, BadGitName): | ||
pass | ||
else: | ||
if git_repo.head.commit.hexsha == job.project.scm_revision: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this to cover the scenario where they gave a specific revision? Rather than a branch or a tag?
awx/main/tasks.py
Outdated
project_path = p.get_project_path(check_if_exists=False) | ||
git_repo = git.Repo(project_path) | ||
try: | ||
commit = git_repo.commit(instance.scm_branch) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this works on all ref types like tags and branches?
@@ -2748,16 +2753,28 @@ def to_representation(self, obj): | |||
|
|||
def validate(self, attrs): | |||
if 'project' in self.fields and 'playbook' in self.fields: | |||
project = attrs.get('project', self.instance and self.instance.project or None) | |||
project = attrs.get('project', self.instance.project if self.instance else None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes please.
migrations.AlterField( | ||
model_name='project', | ||
name='scm_update_cache_timeout', | ||
field=models.PositiveIntegerField(blank=True, default=0, help_text='The number of seconds after the last project update ran that a new project update will be launched as a job dependency.'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only changed because the help_text
got an extra space in it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is correct, two words ran together. I figured this is a good time to fix it because I was already migrating fields on the model.
awx/main/tasks.py
Outdated
logger.info('Skipping project sync for {} because commit is locally available'.format(job.log_format)) | ||
needs_sync = False # requested commit is already locally available | ||
except (ValueError, BadGitName): | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we put a logger.error()
here so people can see in the logs that they put in an invalid ref?
ce2e4ac
to
b73e121
Compare
# manual projects are not synced, user has responsibility for that | ||
needs_sync = False | ||
elif not os.path.exists(project_path): | ||
logger.debug('Performing fresh clone of {} on this instance.'.format(job.project)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These added logging statements here all seem like they should probably be info-level, not debug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/ansible/awx/pull/3882/files#diff-8f5e2fe91e83c971fc84cb35476362db
A lot of the INFO-level logs got axed en masse (almost all, really), as per the reasons there. I raised the level of some select log statements in this PR. For "Skipping project sync", I can buy INFO, because it explains the lack of a unified job. But for statements like this one, they fit in the category of normal cluster operation and that seems to fit in the DEBUG stream precedent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree DEBUG
is more appropriate here - this is just informational regarding work we're doing, and it's not an abnormal thing to have happen. Raising the log level will probably make the logs pretty noisy.
b73e121
to
1ee1645
Compare
This comment has been minimized.
This comment has been minimized.
052a945
to
2894ade
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- ui code changes look good to me
- Allow JT specification and prompting for project branch #4265 (comment) should be resolved by addeff2
- double display of errors (both under the field and in an alert) is more than likely a pre-existing issue with our error handling utility so I've made a github issue for it alert and field-level error sometimes shown for job template forms #4464
Update migration syntax to Django 2 fix status bug where canceled switched to error
* just like we support ansible-galaxy role install, support ansible-galaxy collection install
* ansible:devel now has ansible-galaxy collection support
Addresses some cases where collection requirements do not exist collection requirements cannot be evaluated Consolidate logic for roles and collection installs
* Similar to roles/requirements.yml sync optimization logic.
bump migration fine tune validation of project allow_override return highly custom error message Restore branch after syncs to address bugs encountered after changing scm_refspec remove unused code to determine scm_revision Check Ansible version before project update and do not install collections if Ansible version too old Add docs related to project branch override New file specific to branch override and refspec Complete docs on collections to reflect current implementation and give a folder tree example Update clustering docs related to project syncs Fix bug where git depth was ignored during the local clone from project folder to run folder Fix bug where submodules were not copied
- add refspec field to project - update refspec and branch help text on project form - add refspec field to job detail - adjust form gen and ProcessErrors to show api errors for checkbox_groups correctly - consolidate showPromptButton conditionals and fix the add/edit workflow node one for showing prompt when only branch is promptable
Additional API housekeeping, removing unused code Treat default branch as no branch provided
addeff2
to
be21a8b
Compare
Build succeeded.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This lgtm
Build succeeded (gate pipeline).
|
Restructuring modules so that lookup don't happen if deleting
SUMMARY
Implements the core of #282
Decisions that are non-obvious from the prior discussion:
allow_override
being True will behave the same as other projects (offline runs are possible). I still would argue that this isn't consistent, and will be a surprise to the user, but any decision here would have problems with communication.ISSUE TYPE
COMPONENT NAME
ADDITIONAL INFORMATION
We hope to handle in another PR: