jira-ruby 2.3.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.github/dependabot.yml +6 -0
  5. data/.github/workflows/CI.yml +30 -0
  6. data/.github/workflows/codeql.yml +96 -0
  7. data/.github/workflows/rubocop.yml +18 -0
  8. data/.gitignore +3 -1
  9. data/.rubocop.yml +123 -0
  10. data/.yardopts +4 -0
  11. data/Gemfile +11 -3
  12. data/Guardfile +2 -0
  13. data/README.md +94 -19
  14. data/Rakefile +3 -4
  15. data/jira-ruby.gemspec +12 -17
  16. data/lib/jira/atlassian/jwt.rb +76 -0
  17. data/lib/jira/base.rb +37 -36
  18. data/lib/jira/base_factory.rb +4 -1
  19. data/lib/jira/client.rb +132 -51
  20. data/lib/jira/has_many_proxy.rb +32 -28
  21. data/lib/jira/http_client.rb +80 -13
  22. data/lib/jira/http_error.rb +4 -0
  23. data/lib/jira/jwt_client.rb +19 -43
  24. data/lib/jira/oauth_client.rb +68 -3
  25. data/lib/jira/railtie.rb +2 -0
  26. data/lib/jira/request_client.rb +31 -2
  27. data/lib/jira/resource/agile.rb +7 -9
  28. data/lib/jira/resource/applinks.rb +5 -3
  29. data/lib/jira/resource/attachment.rb +144 -4
  30. data/lib/jira/resource/board.rb +5 -3
  31. data/lib/jira/resource/board_configuration.rb +2 -0
  32. data/lib/jira/resource/comment.rb +14 -0
  33. data/lib/jira/resource/component.rb +2 -0
  34. data/lib/jira/resource/createmeta.rb +7 -5
  35. data/lib/jira/resource/field.rb +13 -12
  36. data/lib/jira/resource/filter.rb +2 -0
  37. data/lib/jira/resource/issue.rb +148 -54
  38. data/lib/jira/resource/issue_picker_suggestions.rb +4 -1
  39. data/lib/jira/resource/issue_picker_suggestions_issue.rb +2 -0
  40. data/lib/jira/resource/issuelink.rb +6 -3
  41. data/lib/jira/resource/issuelinktype.rb +2 -0
  42. data/lib/jira/resource/issuetype.rb +2 -0
  43. data/lib/jira/resource/priority.rb +2 -0
  44. data/lib/jira/resource/project.rb +4 -2
  45. data/lib/jira/resource/properties.rb +56 -0
  46. data/lib/jira/resource/rapidview.rb +5 -3
  47. data/lib/jira/resource/remotelink.rb +2 -0
  48. data/lib/jira/resource/resolution.rb +2 -0
  49. data/lib/jira/resource/serverinfo.rb +2 -0
  50. data/lib/jira/resource/sprint.rb +14 -23
  51. data/lib/jira/resource/status.rb +7 -1
  52. data/lib/jira/resource/status_category.rb +10 -0
  53. data/lib/jira/resource/suggested_issue.rb +2 -0
  54. data/lib/jira/resource/transition.rb +2 -0
  55. data/lib/jira/resource/user.rb +3 -1
  56. data/lib/jira/resource/version.rb +2 -0
  57. data/lib/jira/resource/watcher.rb +3 -2
  58. data/lib/jira/resource/webhook.rb +9 -3
  59. data/lib/jira/resource/worklog.rb +15 -2
  60. data/lib/jira/version.rb +3 -1
  61. data/lib/jira-ruby.rb +6 -3
  62. data/lib/tasks/generate.rake +3 -1
  63. data/spec/data/files/jwt-signed-urls.json +317 -0
  64. data/spec/data/files/short.txt +1 -0
  65. data/spec/integration/attachment_spec.rb +3 -3
  66. data/spec/integration/comment_spec.rb +8 -8
  67. data/spec/integration/component_spec.rb +7 -7
  68. data/spec/integration/field_spec.rb +3 -3
  69. data/spec/integration/issue_spec.rb +21 -18
  70. data/spec/integration/issuelinktype_spec.rb +3 -3
  71. data/spec/integration/issuetype_spec.rb +3 -3
  72. data/spec/integration/priority_spec.rb +3 -3
  73. data/spec/integration/project_spec.rb +8 -8
  74. data/spec/integration/properties_spec.rb +45 -0
  75. data/spec/integration/rapidview_spec.rb +10 -10
  76. data/spec/integration/resolution_spec.rb +3 -3
  77. data/spec/integration/status_category_spec.rb +20 -0
  78. data/spec/integration/status_spec.rb +4 -8
  79. data/spec/integration/transition_spec.rb +5 -4
  80. data/spec/integration/user_spec.rb +34 -11
  81. data/spec/integration/version_spec.rb +7 -7
  82. data/spec/integration/watcher_spec.rb +21 -18
  83. data/spec/integration/webhook_spec.rb +35 -0
  84. data/spec/integration/worklog_spec.rb +8 -8
  85. data/spec/jira/atlassian/jwt_spec.rb +60 -0
  86. data/spec/jira/base_factory_spec.rb +13 -3
  87. data/spec/jira/base_spec.rb +135 -98
  88. data/spec/jira/client_spec.rb +72 -56
  89. data/spec/jira/has_many_proxy_spec.rb +3 -3
  90. data/spec/jira/http_client_spec.rb +94 -27
  91. data/spec/jira/http_error_spec.rb +2 -2
  92. data/spec/jira/oauth_client_spec.rb +14 -8
  93. data/spec/jira/request_client_spec.rb +4 -4
  94. data/spec/jira/resource/agile_spec.rb +32 -32
  95. data/spec/jira/resource/attachment_spec.rb +170 -57
  96. data/spec/jira/resource/board_spec.rb +24 -23
  97. data/spec/jira/resource/createmeta_spec.rb +48 -48
  98. data/spec/jira/resource/field_spec.rb +44 -27
  99. data/spec/jira/resource/filter_spec.rb +7 -6
  100. data/spec/jira/resource/issue_picker_suggestions_spec.rb +17 -17
  101. data/spec/jira/resource/issue_spec.rb +159 -93
  102. data/spec/jira/resource/jira_picker_suggestions_issue_spec.rb +3 -3
  103. data/spec/jira/resource/project_factory_spec.rb +3 -2
  104. data/spec/jira/resource/project_spec.rb +16 -16
  105. data/spec/jira/resource/sprint_spec.rb +88 -9
  106. data/spec/jira/resource/status_spec.rb +21 -0
  107. data/spec/jira/resource/user_factory_spec.rb +5 -5
  108. data/spec/jira/resource/worklog_spec.rb +4 -4
  109. data/spec/mock_responses/board/1_issues.json +2 -1
  110. data/spec/mock_responses/issue/10002/properties/foo.json +4 -0
  111. data/spec/mock_responses/issue/10002/properties/xyz.json +4 -0
  112. data/spec/mock_responses/issue/10002/properties/xyz.put.json +4 -0
  113. data/spec/mock_responses/issue/10002/properties.json +12 -0
  114. data/spec/mock_responses/issue.json +1 -0
  115. data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.full.json +2 -1
  116. data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.json +2 -1
  117. data/spec/mock_responses/sprint/1.json +13 -0
  118. data/spec/mock_responses/status/1.json +8 -1
  119. data/spec/mock_responses/status.json +40 -5
  120. data/spec/mock_responses/statuscategory/1.json +7 -0
  121. data/spec/mock_responses/statuscategory.json +30 -0
  122. data/spec/mock_responses/{user_username=admin.json → user_accountId=1234567890abcdef01234567.json} +2 -1
  123. data/spec/spec_helper.rb +1 -0
  124. data/spec/support/clients_helper.rb +5 -7
  125. data/spec/support/mock_client.rb +9 -0
  126. data/spec/support/mock_response.rb +8 -0
  127. data/spec/support/shared_examples/integration.rb +51 -58
  128. metadata +45 -257
  129. data/.travis.yml +0 -9
  130. data/example.rb +0 -232
  131. data/http-basic-example.rb +0 -113
  132. data/lib/jira/resource/sprint_report.rb +0 -8
  133. data/lib/jira/tasks.rb +0 -0
  134. data/spec/integration/webhook.rb +0 -25
  135. data/spec/jira/jwt_uri_builder_spec.rb +0 -59
  136. data/spec/mock_responses/jira/rest/webhooks/1.0/webhook.json +0 -11
  137. data/spec/mock_responses/webhook/webhook.json +0 -11
  138. /data/spec/mock_responses/{jira/rest/webhooks/1.0/webhook → webhook}/2.json +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 113ad755633d6eb87e63d7a97d3228f6649828547c01dee1ae1900ef0d575e2d
4
- data.tar.gz: d59620f52976814ee7db58df10213bdb512f042a8b8214789ed07288f2899b65
3
+ metadata.gz: 4a043cafa57aad32acfda37495a8419b4511581786620049cb6264a05265aefb
4
+ data.tar.gz: 2c3b66dd69faaef351e043b10c62f3cfd7662e003905363db6bdbf458bfb10b1
5
5
  SHA512:
6
- metadata.gz: e523698732b5cef8a220259ccf5c42c568ac7eea435ee2ed2f2018cdd25959597d23337a67fac037e00be85a8838d9d32a2c79a156da008380699d2c9529cb03
7
- data.tar.gz: cefe63455cb070951d73420dc1144b0c0a4651836427f507d218d3eb0780936e6a740842f6f2df8f68b14be8034bb196b4f5069d21ac0c3cd9e2a4292e43b456
6
+ metadata.gz: 677a496c74235ea213ac92416b9dfb303e56bc04ea94b617134925ce744c25bd81583b2516a342c347a935959795c35813245499efcf2c058b075d308ef51454
7
+ data.tar.gz: ef42dd385a24ff73526e8e2d21fedb0af60832444f9d1e43c0c23a1cca58da61751a24901430abf0650cffacdd7b41ff28fa7620deb195ede7081af504eb4295
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: Bug
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ A runnable code example to reproduce the issue.
15
+
16
+ **Expected behavior**
17
+ A clear and concise description of what you expected to happen.
18
+
19
+ **Additional context**
20
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: Feature
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context about the feature request here.
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "bundler"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -0,0 +1,30 @@
1
+ name: Ruby
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ name: CI-tests
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby:
13
+ - '4.0'
14
+ - '3.4'
15
+ - '3.3'
16
+ - '3.2'
17
+ - '3.1'
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ bundler-cache: true
26
+
27
+ - name: Run tests
28
+ run: |
29
+ bundle exec rake jira:generate_public_cert
30
+ bundle exec rake spec
@@ -0,0 +1,96 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ #
7
+ # ******** NOTE ********
8
+ # We have attempted to detect the languages in your repository. Please check
9
+ # the `language` matrix defined below to confirm you have the correct set of
10
+ # supported CodeQL languages.
11
+ #
12
+ name: "CodeQL"
13
+
14
+ on:
15
+ push:
16
+ branches: [ "master" ]
17
+ paths-ignore:
18
+ - '**/*.md'
19
+ pull_request:
20
+ branches: [ "master" ]
21
+ paths-ignore:
22
+ - '**/*.md'
23
+ schedule:
24
+ - cron: '0 13 * * *'
25
+
26
+ jobs:
27
+ analyze:
28
+ name: Analyze (${{ matrix.language }})
29
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
30
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
31
+ # - https://gh.io/supported-runners-and-hardware-resources
32
+ # - https://gh.io/using-larger-runners (GitHub.com only)
33
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
34
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
35
+ timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
36
+ permissions:
37
+ # required for all workflows
38
+ security-events: write
39
+
40
+ # required to fetch internal or private CodeQL packs
41
+ packages: read
42
+
43
+ # only required for workflows in private repositories
44
+ actions: read
45
+ contents: read
46
+
47
+ strategy:
48
+ fail-fast: false
49
+ matrix:
50
+ include:
51
+ - language: ruby
52
+ build-mode: none
53
+ # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
54
+ # Use `c-cpp` to analyze code written in C, C++ or both
55
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
56
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
57
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
58
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
59
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
60
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
61
+ steps:
62
+ - name: Checkout repository
63
+ uses: actions/checkout@v4
64
+
65
+ # Initializes the CodeQL tools for scanning.
66
+ - name: Initialize CodeQL
67
+ uses: github/codeql-action/init@v3
68
+ with:
69
+ languages: ${{ matrix.language }}
70
+ build-mode: ${{ matrix.build-mode }}
71
+ # If you wish to specify custom queries, you can do so here or in a config file.
72
+ # By default, queries listed here will override any specified in a config file.
73
+ # Prefix the list here with "+" to use these queries and those in the config file.
74
+
75
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
76
+ # queries: security-extended,security-and-quality
77
+
78
+ # If the analyze step fails for one of the languages you are analyzing with
79
+ # "We were unable to automatically build your code", modify the matrix above
80
+ # to set the build mode to "manual" for that language. Then modify this step
81
+ # to build your code.
82
+ # ℹ️ Command-line programs to run using the OS shell.
83
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
84
+ - if: matrix.build-mode == 'manual'
85
+ run: |
86
+ echo 'If you are using a "manual" build mode for one or more of the' \
87
+ 'languages you are analyzing, replace this with the commands to build' \
88
+ 'your code, for example:'
89
+ echo ' make bootstrap'
90
+ echo ' make release'
91
+ exit 1
92
+
93
+ - name: Perform CodeQL Analysis
94
+ uses: github/codeql-action/analyze@v3
95
+ with:
96
+ category: "/language:${{matrix.language}}"
@@ -0,0 +1,18 @@
1
+ name: Rubocop
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ rubocop:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - name: Set up Ruby
12
+ uses: ruby/setup-ruby@v1
13
+ with:
14
+ ruby-version: '3.4'
15
+ bundler-cache: true
16
+ - name: Run rubocop
17
+ run: |
18
+ bundle exec rubocop --format github
data/.gitignore CHANGED
@@ -8,6 +8,8 @@ pkg/*
8
8
  *.pem
9
9
  .DS_STORE
10
10
  doc
11
- .ruby-version
11
+ .ruby-version
12
+ .yardoc
13
+ doc
12
14
 
13
15
  .rakeTasks
data/.rubocop.yml ADDED
@@ -0,0 +1,123 @@
1
+ plugins:
2
+ - rubocop-rspec
3
+
4
+ AllCops:
5
+ Exclude:
6
+ - 'vendor/**/*'
7
+ NewCops: enable
8
+ TargetRubyVersion: 3.1
9
+
10
+ Naming/FileName:
11
+ Exclude:
12
+ - 'lib/jira-ruby.rb'
13
+
14
+ Naming/MethodName:
15
+ Enabled: false
16
+
17
+ Style/Documentation:
18
+ Enabled: false
19
+
20
+ Style/FrozenStringLiteralComment:
21
+ Exclude:
22
+ - 'spec/**/*'
23
+
24
+ ##
25
+ # Temporarily Disable
26
+ #
27
+ # We are going to disable these and fix in pull requests
28
+ ##
29
+ Layout/LineLength:
30
+ Enabled: false
31
+
32
+ Lint/ConstantDefinitionInBlock:
33
+ Enabled: false
34
+
35
+ Lint/EmptyClass:
36
+ Enabled: false
37
+
38
+ Lint/IneffectiveAccessModifier:
39
+ Enabled: false
40
+
41
+ Lint/MissingSuper:
42
+ Enabled: false
43
+
44
+ Metrics/AbcSize:
45
+ Enabled: false
46
+
47
+ Metrics/ClassLength:
48
+ Enabled: false
49
+
50
+ Metrics/CyclomaticComplexity:
51
+ Enabled: false
52
+
53
+ Metrics/MethodLength:
54
+ Enabled: false
55
+
56
+ Metrics/PerceivedComplexity:
57
+ Enabled: false
58
+
59
+ Naming/AccessorMethodName:
60
+ Enabled: false
61
+
62
+ Naming/HeredocDelimiterNaming:
63
+ Enabled: false
64
+
65
+ Naming/PredicatePrefix:
66
+ Enabled: false
67
+
68
+ Naming/PredicateMethod:
69
+ AllowBangMethods: true
70
+
71
+ Naming/VariableNumber:
72
+ Enabled: false
73
+
74
+ RSpec/ExampleLength:
75
+ Enabled: false
76
+
77
+ RSpec/ExpectInHook:
78
+ Enabled: false
79
+
80
+ RSpec/IndexedLet:
81
+ Enabled: false
82
+
83
+ RSpec/InstanceVariable:
84
+ Enabled: false
85
+
86
+ RSpec/LeakyConstantDeclaration:
87
+ Enabled: false
88
+
89
+ RSpec/MessageSpies:
90
+ Enabled: false
91
+
92
+ RSpec/MultipleExpectations:
93
+ Enabled: false
94
+
95
+ RSpec/MultipleMemoizedHelpers:
96
+ Enabled: false
97
+
98
+ RSpec/NamedSubject:
99
+ Enabled: false
100
+
101
+ RSpec/NestedGroups:
102
+ Enabled: false
103
+
104
+ RSpec/ReceiveMessages:
105
+ Enabled: false
106
+
107
+ RSpec/SpecFilePathFormat:
108
+ Enabled: false
109
+
110
+ RSpec/StubbedMock:
111
+ Enabled: false
112
+
113
+ RSpec/SubjectStub:
114
+ Enabled: false
115
+
116
+ RSpec/VerifiedDoubles:
117
+ Enabled: false
118
+
119
+ Style/MissingRespondToMissing:
120
+ Enabled: false
121
+
122
+ Style/OptionalBooleanParameter:
123
+ Enabled: false
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --title "Jira Ruby"
2
+ --no-private
3
+ lib/**/*.rb
4
+
data/Gemfile CHANGED
@@ -1,13 +1,21 @@
1
- source 'http://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  group :development do
4
- gem 'guard'
5
- gem 'guard-rspec'
6
+ gem 'guard', '~> 2.18', '>= 2.18.1'
7
+ gem 'guard-rspec', '~> 4.7', '>= 4.7.3'
8
+ gem 'railties'
9
+ gem 'rake', '~> 13.2', '>= 13.2.1'
10
+ gem 'rspec', '~> 3.0', '>= 3.13'
6
11
  gem 'wdm', '>= 0.1.0' if Gem.win_platform?
12
+ gem 'webmock', '~> 3.23', '>= 3.23.0'
7
13
  end
8
14
 
9
15
  group :development, :test do
10
16
  gem 'pry' # this was in the original Gemfile - but only needed in development & test
17
+ gem 'rubocop'
18
+ gem 'rubocop-rspec', require: false
11
19
  end
12
20
 
13
21
  # Specify your gem's dependencies in jira_api.gemspec
data/Guardfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  gem 'wdm', '>= 0.1.0' if Gem.win_platform?
2
4
  gem 'rspec', '~> 3.0.0'
3
5
 
data/README.md CHANGED
@@ -1,37 +1,113 @@
1
1
  # JIRA API Gem
2
2
 
3
- [![Code Climate](https://codeclimate.com/github/sumoheavy/jira-ruby.svg)](https://codeclimate.com/github/sumoheavy/jira-ruby)
4
- [![Build Status](https://travis-ci.org/sumoheavy/jira-ruby.svg?branch=master)](https://travis-ci.org/sumoheavy/jira-ruby)
3
+ [![Build Status](https://github.com/sumoheavy/jira-ruby/actions/workflows/CI.yml/badge.svg)](https://github.com/sumoheavy/jira-ruby/actions/workflows/CI.yml)
5
4
 
6
5
  This gem provides access to the Atlassian JIRA REST API.
7
6
 
8
- ## Slack
7
+ ## Example usage
9
8
 
10
- Join our Slack channel! You can find us [here](https://jira-ruby-slackin.herokuapp.com/)
9
+ # Jira Ruby API - Sample Usage
11
10
 
12
- ## Example usage
11
+ This sample usage demonstrates how you can interact with JIRA's API using the [jira-ruby gem](https://github.com/sumoheavy/jira-ruby).
13
12
 
14
- ```ruby
15
- require 'rubygems'
16
- require 'jira-ruby'
13
+ ### Dependencies
14
+
15
+ Before running, install the `jira-ruby` gem:
17
16
 
17
+ ```shell
18
+ gem install jira-ruby
19
+ ```
20
+
21
+ ### Sample Usage
22
+ Connect to JIRA
23
+ Firstly, establish a connection with your JIRA instance by providing a few configuration parameters:
24
+ There are other ways to connect to JIRA listed below | [Personal Access Token](#configuring-jira-to-use-personal-access-tokens-auth)
25
+ - private_key_file: The path to your RSA private key file.
26
+ - consumer_key: Your consumer key.
27
+ - site: The URL of your JIRA instance.
28
+
29
+ ```ruby
18
30
  options = {
19
- :username => 'username',
20
- :password => 'pass1234',
21
- :site => 'http://mydomain.atlassian.net:443/',
22
- :context_path => '',
23
- :auth_type => :basic
31
+ :private_key_file => "rsakey.pem",
32
+ :context_path => '',
33
+ :consumer_key => 'your_consumer_key',
34
+ :site => 'your_jira_instance_url'
24
35
  }
25
36
 
26
37
  client = JIRA::Client.new(options)
38
+ ```
27
39
 
28
- project = client.Project.find('SAMPLEPROJECT')
40
+ ### Retrieve and Display Projects
29
41
 
30
- project.issues.each do |issue|
31
- puts "#{issue.id} - #{issue.summary}"
42
+ After establishing the connection, you can fetch all projects and display their key and name:
43
+ ```ruby
44
+ projects = client.Project.all
45
+
46
+ projects.each do |project|
47
+ puts "Project -> key: #{project.key}, name: #{project.name}"
32
48
  end
33
49
  ```
34
50
 
51
+ ### Handling Fields by Name
52
+ The jira-ruby gem allows you to refer to fields by their custom names rather than identifiers. Make sure to map fields before using them:
53
+
54
+ ```ruby
55
+ client.Field.map_fields
56
+
57
+ old_way = issue.customfield_12345
58
+
59
+ # Note: The methods mapped here adopt a unique style combining PascalCase and snake_case conventions.
60
+ new_way = issue.Special_Field
61
+ ```
62
+
63
+ ### JQL Queries
64
+ To find issues based on specific criteria, you can use JIRA Query Language (JQL):
65
+
66
+ ```ruby
67
+ client.Issue.jql(a_normal_jql_search, fields:[:description, :summary, :Special_field, :created])
68
+ ```
69
+
70
+ ### Several actions can be performed on the Issue object such as create, update, transition, delete, etc:
71
+ ### Creating an Issue
72
+ ```ruby
73
+ issue = client.Issue.build
74
+ labels = ['label1', 'label2']
75
+ issue.save({
76
+ "fields" => {
77
+ "summary" => "blarg from in example.rb",
78
+ "project" => {"key" => "SAMPLEPROJECT"},
79
+ "issuetype" => {"id" => "3"},
80
+ "labels" => labels,
81
+ "priority" => {"id" => "1"}
82
+ }
83
+ })
84
+ ```
85
+
86
+ ### Updating/Transitioning an Issue
87
+ ```ruby
88
+ issue = client.Issue.find("10002")
89
+ issue.save({"fields"=>{"summary"=>"EVEN MOOOOOOARRR NINJAAAA!"}})
90
+
91
+ issue_transition = issue.transitions.build
92
+ issue_transition.save!('transition' => {'id' => transition_id})
93
+ ```
94
+
95
+ ### Deleting an Issue
96
+ ```ruby
97
+ issue = client.Issue.find('SAMPLEPROJECT-2')
98
+ issue.delete
99
+ ```
100
+
101
+ ### Other Capabilities
102
+ Apart from the operations listed above, this API wrapper supports several other capabilities like:
103
+ • Searching for a user
104
+ • Retrieving an issue's watchers
105
+ • Changing the assignee of an issue
106
+ • Adding attachments and comments to issues
107
+ • Managing issue links and much more.
108
+
109
+ Not all examples are shown in this README; refer to the complete script example for a full overview of the capabilities supported by this API wrapper.
110
+
35
111
  ## Links to JIRA REST API documentation
36
112
 
37
113
  * [Overview](https://developer.atlassian.com/display/JIRADEV/JIRA+REST+APIs)
@@ -87,7 +163,7 @@ key.
87
163
  > After you have entered all the information click OK and ensure OAuth authentication is
88
164
  > enabled.
89
165
 
90
- For 2 legged oauth in server mode only, not in cloud based JIRA, make sure to `Allow 2-Legged OAuth`
166
+ For two legged oauth in server mode only, not in cloud based JIRA, make sure to `Allow 2-Legged OAuth`
91
167
 
92
168
  ## Configuring JIRA to use HTTP Basic Auth
93
169
 
@@ -148,8 +224,7 @@ api_token = API_TOKEN_OBTAINED_FROM_JIRA_UI
148
224
  options = {
149
225
  :site => 'http://mydomain.atlassian.net:443/',
150
226
  :context_path => '',
151
- :username => '<the email you sign-in to Jira>',
152
- :password => api_token,
227
+ :default_headers => { 'Authorization' => "Bearer #{api_token}" },
153
228
  :auth_type => :basic
154
229
  }
155
230
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
 
3
5
  require 'rubygems'
@@ -13,13 +15,10 @@ task test: %i[prepare spec]
13
15
  desc 'Prepare and run rspec tests'
14
16
  task :prepare do
15
17
  rsa_key = File.expand_path('rsakey.pem')
16
- unless File.exist?(rsa_key)
17
- Rake::Task['jira:generate_public_cert'].invoke
18
- end
18
+ Rake::Task['jira:generate_public_cert'].invoke unless File.exist?(rsa_key)
19
19
  end
20
20
 
21
21
  desc 'Run RSpec tests'
22
- # RSpec::Core::RakeTask.new(:spec)
23
22
  RSpec::Core::RakeTask.new(:spec, [] => [:prepare]) do |task|
24
23
  task.rspec_opts = ['--color', '--format', 'doc']
25
24
  end
data/jira-ruby.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.push File.expand_path('lib', __dir__)
2
4
  require 'jira/version'
3
5
 
@@ -9,27 +11,20 @@ Gem::Specification.new do |s|
9
11
  s.summary = 'Ruby Gem for use with the Atlassian JIRA REST API'
10
12
  s.description = 'API for JIRA'
11
13
  s.licenses = ['MIT']
12
- s.metadata = { 'source_code_uri' => 'https://github.com/sumoheavy/jira-ruby' }
14
+ s.metadata = {
15
+ 'source_code_uri' => 'https://github.com/sumoheavy/jira-ruby',
16
+ 'rubygems_mfa_required' => 'true'
17
+ }
13
18
 
14
- s.required_ruby_version = '>= 1.9.3'
19
+ s.required_ruby_version = '>= 3.1.0'
15
20
 
16
21
  s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
22
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
23
  s.require_paths = ['lib']
20
24
 
21
- # Runtime Dependencies
22
- s.add_runtime_dependency 'activesupport'
23
- s.add_runtime_dependency 'atlassian-jwt'
24
- s.add_runtime_dependency 'multipart-post'
25
- s.add_runtime_dependency 'oauth', '~> 0.5', '>= 0.5.0'
26
-
27
- # Development Dependencies
28
- s.add_development_dependency 'guard', '~> 2.13', '>= 2.13.0'
29
- s.add_development_dependency 'guard-rspec', '~> 4.6', '>= 4.6.5'
30
- s.add_development_dependency 'pry', '~> 0.10', '>= 0.10.3'
31
- s.add_development_dependency 'railties'
32
- s.add_development_dependency 'rake', '~> 10.3', '>= 10.3.2'
33
- s.add_development_dependency 'rspec', '~> 3.0', '>= 3.0.0'
34
- s.add_development_dependency 'webmock', '~> 1.18', '>= 1.18.0'
25
+ s.add_dependency 'activesupport'
26
+ s.add_dependency 'cgi'
27
+ s.add_dependency 'jwt', '>= 2.1'
28
+ s.add_dependency 'multipart-post'
29
+ s.add_dependency 'oauth', '~> 1.0'
35
30
  end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2013 Atlassian Pty Ltd.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'jwt'
18
+ require 'uri'
19
+ require 'cgi'
20
+
21
+ module JIRA
22
+ module Atlassian
23
+ module Jwt
24
+ class << self
25
+ CANONICAL_QUERY_SEPARATOR = '&'
26
+ ESCAPED_CANONICAL_QUERY_SEPARATOR = '%26'
27
+
28
+ def create_canonical_request(uri, http_method, base_uri)
29
+ uri = URI.parse(uri) unless uri.is_a? URI
30
+ base_uri = URI.parse(base_uri) unless base_uri.is_a? URI
31
+
32
+ [
33
+ http_method.upcase,
34
+ canonicalize_uri(uri, base_uri),
35
+ canonicalize_query_string(uri.query)
36
+ ].join(CANONICAL_QUERY_SEPARATOR)
37
+ end
38
+
39
+ def build_claims(issuer, url, http_method, base_url = '', issued_at = nil, expires = nil, attributes = {}) # rubocop:disable Metrics/ParameterLists
40
+ issued_at ||= Time.now.to_i
41
+ expires ||= issued_at + 60
42
+ qsh = Digest::SHA256.hexdigest(create_canonical_request(url, http_method, base_url))
43
+
44
+ {
45
+ iss: issuer,
46
+ iat: issued_at,
47
+ exp: expires,
48
+ qsh: qsh
49
+ }.merge(attributes)
50
+ end
51
+
52
+ def canonicalize_uri(uri, base_uri)
53
+ path = uri.path.sub(/^#{base_uri.path}/, '')
54
+ path = '/' if path.nil? || path.empty?
55
+ path = "/#{path}" unless path.start_with? '/'
56
+ path.chomp!('/') if path.length > 1
57
+ path.gsub(CANONICAL_QUERY_SEPARATOR, ESCAPED_CANONICAL_QUERY_SEPARATOR)
58
+ end
59
+
60
+ def canonicalize_query_string(query)
61
+ return '' if query.nil? || query.empty?
62
+
63
+ query = CGI.parse(query)
64
+ query.delete('jwt')
65
+ query.each do |k, v|
66
+ query[k] = v.map { |a| CGI.escape a }.join(',') if v.is_a? Array
67
+ query[k].gsub!('+', '%20') # Use %20, not CGI.escape default of "+"
68
+ query[k].gsub!('%7E', '~') # Unescape "~" per JS tests
69
+ end
70
+ query = query.sort.to_h
71
+ query.map { |k, v| "#{CGI.escape k}=#{v}" }.join(CANONICAL_QUERY_SEPARATOR)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end