Skip to content

feat: add recover option to mr create command

Jaime Martinez requested to merge 472-mr-recovery into main

Description

This MR introduces a -recover flag as discussed in #472 (closed). The intent is to save the glab mr create [OPTIONS] into a file if the creation fails. If the file exists, we try to load the contents into the issue options and attempt to create the MR again.

Related Issues

Related to Friendlier recovery when issue/mr create fails (#472 - closed)

How has this been tested?

The easiest way to test locally is to force a failure before creating the issue with the API:

  1. Return an error early in commands/mr/create/mr_create.go#L480:

    return errors.New("fail on purpose")
  2. Build the binary with the deliberate error running make

  3. Use a test project, I'm using https://gitlab.com/jaime/glab-cli-tests for my tests. Check it out locally and cd into the location

  4. Once in the test location, use the glab binary that you built, e.g. /Users/jaime/dev/gitlab/cli/bin/glab

  5. Attempt to create an issue using the -recover flag and verify it fails

    glab mr create --recover  --draft -f -t "add test files"
    Failed to create MR. Created recovery file: /Users/jaime/.config/glab-cli/recover/jaime/glab-cli-tests/mr.json
    Run the command again with the '--recover' option to retry
    fail on purpose
  6. Verify the file exists and contains the correct details

Click to expand

cat /Users/jaime/.config/glab-cli/recover/jaime/glab-cli-tests/mr.json | jq
{
  "title": "Draft: add test files",
  "description": "- added test file  \n- another file  \n",
  "source_branch": "test-mr-recovery",
  "target_branch": "main",
  "target_tracking_branch": "origin/main",
  "autofill": true,
  "is_draft": true,
  "should_push": true,
  "source_project": {
    "id": 40768206,
    "description": "",
    "default_branch": "main",
    "public": false,
    "visibility": "public",
    "ssh_url_to_repo": "git@gitlab.com:jaime/glab-cli-tests.git",
    "http_url_to_repo": "https://gitlab.com/jaime/glab-cli-tests.git",
    "web_url": "https://gitlab.com/jaime/glab-cli-tests",
    "readme_url": "https://gitlab.com/jaime/glab-cli-tests/-/blob/main/README.md",
    "tag_list": [],
    "topics": [],
    "owner": {
      "id": 4082686,
      "username": "jaime",
      "email": "",
      "name": "Jaime Martinez",
      "state": "active",
      "web_url": "https://gitlab.com/jaime",
      "created_at": null,
      "bio": "",
      "bot": false,
      "location": "",
      "public_email": "",
      "skype": "",
      "linkedin": "",
      "twitter": "",
      "website_url": "",
      "organization": "",
      "job_title": "",
      "extern_uid": "",
      "provider": "",
      "theme_id": 0,
      "last_activity_on": null,
      "color_scheme_id": 0,
      "is_admin": false,
      "avatar_url": "https://gitlab.com/uploads/-/system/user/avatar/4082686/avatar.png",
      "can_create_group": false,
      "can_create_project": false,
      "projects_limit": 0,
      "current_sign_in_at": null,
      "current_sign_in_ip": null,
      "last_sign_in_at": null,
      "last_sign_in_ip": null,
      "confirmed_at": null,
      "two_factor_enabled": false,
      "note": "",
      "identities": null,
      "external": false,
      "private_profile": false,
      "shared_runners_minutes_limit": 0,
      "extra_shared_runners_minutes_limit": 0,
      "using_license_seat": false,
      "custom_attributes": null,
      "namespace_id": 0
    },
    "name": "glab-cli-tests",
    "name_with_namespace": "Jaime Martinez / glab-cli-tests",
    "path": "glab-cli-tests",
    "path_with_namespace": "jaime/glab-cli-tests",
    "issues_enabled": true,
    "open_issues_count": 9,
    "merge_requests_enabled": true,
    "approvals_before_merge": 0,
    "jobs_enabled": true,
    "wiki_enabled": true,
    "snippets_enabled": true,
    "resolve_outdated_diff_discussions": false,
    "container_expiration_policy": {
      "cadence": "1d",
      "keep_n": 10,
      "older_than": "90d",
      "name_regex_delete": "",
      "name_regex_keep": "",
      "enabled": false,
      "next_run_at": "2022-11-05T03:52:31.746Z"
    },
    "container_registry_enabled": true,
    "container_registry_access_level": "enabled",
    "container_registry_image_prefix": "registry.gitlab.com/jaime/glab-cli-tests",
    "created_at": "2022-11-04T03:52:31.722Z",
    "last_activity_at": "2022-12-04T00:10:22.585Z",
    "creator_id": 4082686,
    "namespace": {
      "id": 5336147,
      "name": "Jaime Martinez",
      "path": "jaime",
      "kind": "user",
      "full_path": "jaime",
      "parent_id": 0,
      "avatar_url": "/uploads/-/system/user/avatar/4082686/avatar.png",
      "web_url": "https://gitlab.com/jaime"
    },
    "import_status": "none",
    "import_error": "",
    "permissions": {
      "project_access": {
        "access_level": 50,
        "notification_level": "global"
      },
      "group_access": null
    },
    "marked_for_deletion_at": null,
    "empty_repo": false,
    "archived": false,
    "avatar_url": "",
    "license_url": "",
    "license": null,
    "shared_runners_enabled": true,
    "forks_count": 0,
    "star_count": 0,
    "runners_token": "GR1348941Kw1dgWxWtsBC5ffbmUvV",
    "public_builds": false,
    "allow_merge_on_skipped_pipeline": false,
    "only_allow_merge_if_pipeline_succeeds": false,
    "only_allow_merge_if_all_discussions_are_resolved": false,
    "remove_source_branch_after_merge": true,
    "printing_merge_request_link_enabled": true,
    "lfs_enabled": true,
    "repository_storage": "",
    "request_access_enabled": true,
    "merge_method": "merge",
    "forked_from_project": null,
    "mirror": false,
    "mirror_user_id": 0,
    "mirror_trigger_builds": false,
    "only_mirror_protected_branches": false,
    "mirror_overwrites_diverged_branches": false,
    "packages_enabled": true,
    "service_desk_enabled": true,
    "service_desk_address": "contact-project+jaime-glab-cli-tests-40768206-issue-@incoming.gitlab.com",
    "issues_access_level": "enabled",
    "repository_access_level": "enabled",
    "merge_requests_access_level": "enabled",
    "forking_access_level": "enabled",
    "wiki_access_level": "enabled",
    "builds_access_level": "enabled",
    "snippets_access_level": "enabled",
    "pages_access_level": "enabled",
    "operations_access_level": "enabled",
    "analytics_access_level": "enabled",
    "autoclose_referenced_issues": true,
    "suggestion_commit_message": "",
    "auto_cancel_pending_pipelines": "enabled",
    "ci_forward_deployment_enabled": true,
    "squash_option": "default_off",
    "shared_with_groups": [],
    "statistics": {
      "commit_count": 1,
      "storage_size": 73400,
      "repository_size": 73400,
      "wiki_size": 0,
      "lfs_objects_size": 0,
      "job_artifacts_size": 0,
      "pipeline_artifacts_size": 0,
      "packages_size": 0,
      "snippets_size": 0,
      "uploads_size": 0
    },
    "_links": {
      "self": "https://gitlab.com/api/v4/projects/40768206",
      "issues": "https://gitlab.com/api/v4/projects/40768206/issues",
      "merge_requests": "https://gitlab.com/api/v4/projects/40768206/merge_requests",
      "repo_branches": "https://gitlab.com/api/v4/projects/40768206/repository/branches",
      "labels": "https://gitlab.com/api/v4/projects/40768206/labels",
      "events": "https://gitlab.com/api/v4/projects/40768206/events",
      "members": "https://gitlab.com/api/v4/projects/40768206/members"
    },
    "ci_config_path": "",
    "ci_default_git_depth": 20,
    "custom_attributes": null,
    "compliance_frameworks": [],
    "build_coverage_regex": "",
    "build_timeout": 3600,
    "issues_template": "",
    "merge_requests_template": "",
    "keep_latest_artifact": true,
    "merge_pipelines_enabled": false,
    "merge_trains_enabled": false,
    "restrict_user_defined_variables": false,
    "merge_commit_template": "",
    "squash_commit_template": "",
    "auto_devops_deploy_strategy": "continuous",
    "auto_devops_enabled": false,
    "build_git_strategy": "fetch",
    "emails_disabled": false,
    "external_authorization_classification_label": "",
    "requirements_access_level": "enabled",
    "security_and_compliance_access_level": "private"
  },
  "target_project": {
    "id": 40768206,
    "description": "",
    "default_branch": "main",
    "public": false,
    "visibility": "public",
    "ssh_url_to_repo": "git@gitlab.com:jaime/glab-cli-tests.git",
    "http_url_to_repo": "https://gitlab.com/jaime/glab-cli-tests.git",
    "web_url": "https://gitlab.com/jaime/glab-cli-tests",
    "readme_url": "https://gitlab.com/jaime/glab-cli-tests/-/blob/main/README.md",
    "tag_list": [],
    "topics": [],
    "owner": {
      "id": 4082686,
      "username": "jaime",
      "email": "",
      "name": "Jaime Martinez",
      "state": "active",
      "web_url": "https://gitlab.com/jaime",
      "created_at": null,
      "bio": "",
      "bot": false,
      "location": "",
      "public_email": "",
      "skype": "",
      "linkedin": "",
      "twitter": "",
      "website_url": "",
      "organization": "",
      "job_title": "",
      "extern_uid": "",
      "provider": "",
      "theme_id": 0,
      "last_activity_on": null,
      "color_scheme_id": 0,
      "is_admin": false,
      "avatar_url": "https://gitlab.com/uploads/-/system/user/avatar/4082686/avatar.png",
      "can_create_group": false,
      "can_create_project": false,
      "projects_limit": 0,
      "current_sign_in_at": null,
      "current_sign_in_ip": null,
      "last_sign_in_at": null,
      "last_sign_in_ip": null,
      "confirmed_at": null,
      "two_factor_enabled": false,
      "note": "",
      "identities": null,
      "external": false,
      "private_profile": false,
      "shared_runners_minutes_limit": 0,
      "extra_shared_runners_minutes_limit": 0,
      "using_license_seat": false,
      "custom_attributes": null,
      "namespace_id": 0
    },
    "name": "glab-cli-tests",
    "name_with_namespace": "Jaime Martinez / glab-cli-tests",
    "path": "glab-cli-tests",
    "path_with_namespace": "jaime/glab-cli-tests",
    "issues_enabled": true,
    "open_issues_count": 9,
    "merge_requests_enabled": true,
    "approvals_before_merge": 0,
    "jobs_enabled": true,
    "wiki_enabled": true,
    "snippets_enabled": true,
    "resolve_outdated_diff_discussions": false,
    "container_expiration_policy": {
      "cadence": "1d",
      "keep_n": 10,
      "older_than": "90d",
      "name_regex_delete": "",
      "name_regex_keep": "",
      "enabled": false,
      "next_run_at": "2022-11-05T03:52:31.746Z"
    },
    "container_registry_enabled": true,
    "container_registry_access_level": "enabled",
    "container_registry_image_prefix": "registry.gitlab.com/jaime/glab-cli-tests",
    "created_at": "2022-11-04T03:52:31.722Z",
    "last_activity_at": "2022-12-04T00:10:22.585Z",
    "creator_id": 4082686,
    "namespace": {
      "id": 5336147,
      "name": "Jaime Martinez",
      "path": "jaime",
      "kind": "user",
      "full_path": "jaime",
      "parent_id": 0,
      "avatar_url": "/uploads/-/system/user/avatar/4082686/avatar.png",
      "web_url": "https://gitlab.com/jaime"
    },
    "import_status": "none",
    "import_error": "",
    "permissions": {
      "project_access": {
        "access_level": 50,
        "notification_level": "global"
      },
      "group_access": null
    },
    "marked_for_deletion_at": null,
    "empty_repo": false,
    "archived": false,
    "avatar_url": "",
    "license_url": "",
    "license": null,
    "shared_runners_enabled": true,
    "forks_count": 0,
    "star_count": 0,
    "runners_token": "GR1348941Kw1dgWxWtsBC5ffbmUvV",
    "public_builds": false,
    "allow_merge_on_skipped_pipeline": false,
    "only_allow_merge_if_pipeline_succeeds": false,
    "only_allow_merge_if_all_discussions_are_resolved": false,
    "remove_source_branch_after_merge": true,
    "printing_merge_request_link_enabled": true,
    "lfs_enabled": true,
    "repository_storage": "",
    "request_access_enabled": true,
    "merge_method": "merge",
    "forked_from_project": null,
    "mirror": false,
    "mirror_user_id": 0,
    "mirror_trigger_builds": false,
    "only_mirror_protected_branches": false,
    "mirror_overwrites_diverged_branches": false,
    "packages_enabled": true,
    "service_desk_enabled": true,
    "service_desk_address": "contact-project+jaime-glab-cli-tests-40768206-issue-@incoming.gitlab.com",
    "issues_access_level": "enabled",
    "repository_access_level": "enabled",
    "merge_requests_access_level": "enabled",
    "forking_access_level": "enabled",
    "wiki_access_level": "enabled",
    "builds_access_level": "enabled",
    "snippets_access_level": "enabled",
    "pages_access_level": "enabled",
    "operations_access_level": "enabled",
    "analytics_access_level": "enabled",
    "autoclose_referenced_issues": true,
    "suggestion_commit_message": "",
    "auto_cancel_pending_pipelines": "enabled",
    "ci_forward_deployment_enabled": true,
    "squash_option": "default_off",
    "shared_with_groups": [],
    "statistics": {
      "commit_count": 1,
      "storage_size": 73400,
      "repository_size": 73400,
      "wiki_size": 0,
      "lfs_objects_size": 0,
      "job_artifacts_size": 0,
      "pipeline_artifacts_size": 0,
      "packages_size": 0,
      "snippets_size": 0,
      "uploads_size": 0
    },
    "_links": {
      "self": "https://gitlab.com/api/v4/projects/40768206",
      "issues": "https://gitlab.com/api/v4/projects/40768206/issues",
      "merge_requests": "https://gitlab.com/api/v4/projects/40768206/merge_requests",
      "repo_branches": "https://gitlab.com/api/v4/projects/40768206/repository/branches",
      "labels": "https://gitlab.com/api/v4/projects/40768206/labels",
      "events": "https://gitlab.com/api/v4/projects/40768206/events",
      "members": "https://gitlab.com/api/v4/projects/40768206/members"
    },
    "ci_config_path": "",
    "ci_default_git_depth": 20,
    "custom_attributes": null,
    "compliance_frameworks": [],
    "build_coverage_regex": "",
    "build_timeout": 3600,
    "issues_template": "",
    "merge_requests_template": "",
    "keep_latest_artifact": true,
    "merge_pipelines_enabled": false,
    "merge_trains_enabled": false,
    "restrict_user_defined_variables": false,
    "merge_commit_template": "",
    "squash_commit_template": "",
    "auto_devops_deploy_strategy": "continuous",
    "auto_devops_enabled": false,
    "build_git_strategy": "fetch",
    "emails_disabled": false,
    "external_authorization_classification_label": "",
    "requirements_access_level": "enabled",
    "security_and_compliance_access_level": "private"
  }
}
  1. Undo the first step by removing the error in commands/mr/create/mr_create.go#L480

  2. Compile the binary again using make

  3. Try to create the issue again with the -recover flag

    glab mr create --recover
    Recovered create options from file
    ? What's next? Submit
    Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
    remote:
    remote: To create a merge request for test-2, visit:
    remote:   https://gitlab.com/jaime/glab-cli-tests/-/merge_requests/new?merge_request%5Bsource_branch%5D=test-2
    remote:
    To gitlab.com:jaime/glab-cli-tests.git
     * [new branch]      HEAD -> test-2
    branch 'test-2' set up to track 'origin/test-2'.
    
    Creating draft merge request for test-2 into main in jaime/glab-cli-tests
    
    !2 Draft: Draft: Draft: add test files (test-2)
    https://gitlab.com/jaime/glab-cli-tests/-/merge_requests/2
  4. Voila! MR created and the recover file should have been removed

    cat /Users/jaime/.config/glab-cli/recover/jaime/glab-cli-tests/mr.json | jq
    cat: /Users/jaime/.config/glab-cli/recover/jaime/glab-cli-tests/mr.json: No such file or directory

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation
  • Chore (Related to CI or Packaging to platforms)

Next steps

There is an existing issue to create integration tests for the --recover option #1163

Closes #472 (closed)

Edited by Jaime Martinez

Merge request reports