#55 Pr Till Gsoc FInal Eval
Merged 4 years ago by pac23. Opened 4 years ago by pac23.

print cleanup
pac23 • 4 years ago  
add init file
pac23 • 4 years ago  
minor fixes
Manas • 4 years ago  
code cleanup
Manas • 4 years ago  
file added
+2
@@ -0,0 +1,2 @@ 

+ *.pyc

+ /venv 

\ No newline at end of file

file added
+10
@@ -0,0 +1,10 @@ 

+ name: Fedora-change-wrangler-docs

+ 

+ title: Fedora-change-wrangler-docs

+ 

+ version: master

+ 

+ start_page: ROOT:index

+ 

+ nav:

+   - modules/ROOT/nav.adoc 

\ No newline at end of file

file added
+90
@@ -0,0 +1,90 @@ 

+ #!/bin/sh

+ 	

+ 	

+ image="docker.io/antora/antora"

+ 	

+ cmd="--html-url-extension-style=indexify site.yml"

+ 	

+  

+ 	

+ if [ "$(uname)" == "Darwin" ]; then

+ 	

+     # Running on macOS.

+ 	

+     # Let's assume that the user has the Docker CE installed

+ 	

+     # which doesn't require a root password.

+ 	

+     echo ""

+ 	

+     echo "This build script is using Docker container runtime to run the build in an isolated environment."

+ 	

+     echo ""

+ 	

+     docker run --rm -it -v $(pwd):/antora $image $cmd

+ 	

+  

+ 	

+ elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then

+ 	

+     # Running on Linux.

+ 	

+     # Check whether podman is available, else faill back to docker

+ 	

+     # which requires root.

+ 	

+  

+ 	

+     if [ -f /usr/bin/podman ]; then

+ 	

+         echo ""

+ 	

+         echo "This build script is using Podman to run the build in an isolated environment."

+ 	

+         echo ""

+ 	

+ 	podman run --rm -it -v $(pwd):/antora:z $image $cmd

+ 	

+  

+ 	

+     elif [ -f /usr/bin/docker ]; then

+ 	

+         echo ""

+ 	

+         echo "This build script is using Docker to run the build in an isolated environment."

+ 	

+         echo ""

+ 	

+  

+ 	

+         if groups | grep -wq "docker"; then

+ 	

+ 	    docker run --rm -it -v $(pwd):/antora:z $image $cmd

+ 	

+ 	else

+ 	

+             echo ""

+ 	

+             echo "This build script is using $runtime to run the build in an isolated environment. You might be asked for your password."

+ 	

+             echo "You can avoid this by adding your user to the 'docker' group, but be aware of the security implications. See https://docs.docker.com/install/linux/linux-postinstall/."

+ 	

+             echo ""

+ 	

+             sudo docker run --rm -it -v $(pwd):/antora:z $image $cmd

+ 	

+ 	fi

+ 	

+     else

+ 	

+         echo ""

+ 	

+ 	echo "Error: Container runtime haven't been found on your system. Fix it by:"

+ 	

+ 	echo "$ sudo dnf install podman"

+ 	

+ 	exit 1

+ 	

+     fi

+ 	

+ fi 

\ No newline at end of file

@@ -0,0 +1,1 @@ 

+ 

@@ -0,0 +1,34 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: accepting-changes

+ 

+ = Accepting Changes in the Tool

+ 

+ Accept command enables the user to accept a change proosal. It takes the issue no as a argument and initiates the convert functionality followed by creating the issue in bugzilla linked with the pagure repo.

+ 

+ == Usage

+ 

+ include::config.note.adoc[]

+ 

+ Accept has only once command that does everything mentioned in the above sections

+ 

+ Accepts the Change Converts Issue to UserStory creates a Bug in bugzilla

+ "X" stands for issue Refrence/No from taiga

+ 

+ +

+ ----

+ fedora-change-wrangler accept --accept "X"

+ ----

+ 

+ 

+ 

+ The --accept flag is to let the system know that you are passing N number of issue no's.

+ 

+ The --config can be passed as

+ +

+ ----

+ fedora-change-wrangler accept --accept "X" --config

+ ----

+ 

+ 

+ 

+ 

@@ -0,0 +1,38 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: annoucing-mailinglist

+ 

+ = Annoucing to the Mailing list

+ 

+ The Annouce command announces to the Mailing list. It takes the issue refrence no as a argument and initiates the mailing functionality.It will fetch the issue with its description,summary and all other attributes and send a mail as per the predefined email id list in the config.

+ 

+ == Usage

+ 

+ include::config.note.adoc[]

+ 

+ Accept has only one command that does everything mentioned in the above sections

+ 

+ Announces the Issue to the mailing list

+ "X" stands for issue Refrence/No from taiga

+ 

+ +

+ ----

+ fedora-change-wrangler announce --ml "X"

+ ----

+ 

+ Announces the Issue to the mailing list but with the reply header

+ 

+ --reply if not mentioned has the reply option for all emails,

+ if set only the first email adress is set as reply to in the header

+ 

+ +

+ ----

+ fedora-change-wrangler announce --ml "X" --reply

+ ----

+ 

+ The --config header as mentioned in the note above can also be used with all these.

+ 

+ +

+ ----

+ fedora-change-wrangler announce --ml "X" --reply --config

+ ----

+ 

@@ -0,0 +1,11 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: authentica-bugzilla

+ 

+ = Authenticate Bugzilla

+ 

+ Bugzilla authentication is handled by the python-bugzilla module

+ It will ask for the user id and password from the user whenver a function that has the bugzilla functionality is used and saves the token fetched from it in a cookie.

+ For more information checkout the link_here[Developer-Documentation]

+ 

+ 

+ 

@@ -0,0 +1,32 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: authenticate-pagure

+ 

+ = Authenticate Pagure

+ 

+ Pagure requires using a token/key to acess the Rest api.The key is unique to each repository.

+ The auth command with the pagure flag and its subcommands sets the api token for the specfic repositories.

+ 

+ include::config.note.adoc[]

+ 

+ === Set or Reset Taiga Credentials

+ 

+ The API key is required for creating/delteting issues and other enabled functions on the repository.The token is stored securly in your system.

+ 

+ For More information on the technical details of the storage kindly read the link_here[Developer Documentation]

+ 

+ To set/reset the token :

+ 

+ +

+ ----

+ fedora-change-wrangler auth pagure --reset

+ ----

+ 

+ === Test if token is valid

+ 

+ Using this command one may test the set api key/token.This command returns information of the user the repository tied to the api key.

+ 

+ +

+ ----

+ fedora-change-wrangler auth pagure --whoami

+ ----

+ 

@@ -0,0 +1,35 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: authenticate-taiga

+ 

+ = Authenticate Taiga

+ 

+ Taiga requires using a token/key to acess the Rest api.

+ The auth command with the --taiga flag and its sublags retrive the token or refresh it if expired.

+ 

+ include::config.note.adoc[]

+ 

+ === Set or Reset Taiga Credentials

+ 

+ The Credentials required for fetching the token are stored securly in your system.The users Taiga Username and Password would be required to

+ fetch the token.

+ 

+ For More information on the technical details of the storage kindly read the link_here[Developer Documentation]

+ 

+ To set/reset the token :

+ 

+ +

+ ----

+ fedora-change-wrangler auth taiga --reset

+ ----

+ 

+ === Refresh Expired Taiga Api Token

+ 

+ Taiga's token expires every 60 days so it needs to be refreshed.

+ 

+ To refresh the token:

+ 

+ +

+ ----

+ fedora-change-wrangler auth taiga --token

+ ----

+ 

@@ -0,0 +1,47 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: config-set

+ 

+ = Config

+ 

+ The Tool has user defined settting available via the config.The config allows the user to have the tool work with thier own instances of Taiga,Pagure and Bugzilla.

+ It also allows the user to set the sender,reciver email id's for email funcitonality,

+ 

+ === User Defined Config Storage

+ The config can also be stored in a user defined location and the location can be passed as a argument to the tool in various commands.

+ 

+ +

+ ----

+ fedora-change-wrangler auth taiga --config /disk/folder/file.ini

+ ----

+ 

+ === Taiga Config

+ The config.ini file contains a [TAIGA] section which has all the taiga related configurations in it.The file holds the ID's using which taiga maps and identifies the userstories,statuses,custom attributes,epics etc.

+ 

+ Without the ID's the tool would not function thus the user should fetch and set the custom attribtue id's as per the taiga instance they are using.

+ More information to fetch the ID'S can be found in https://taigaio.github.io/taiga-doc/dist/api.html[Taiga Documentation]

+ 

+ +

+ ----

+ [TAIGA]

+ TAIGA_URL = https://teams.fedoraproject.org

+ ----

+ 

+ === Pagure COnfig

+ The config.ini file contains the [PAGURE] section which has all the pagure related configurations in it.The section holds the service ID and the repository url's.

+ 

+ +

+ ----

+ [PAGURE]

+ FESCO_REPO = my repo name

+ RELEASE NOTES REPO = I give this a name

+ ----

+ 

+ === Bugzilla Config

+ The config.ini file contains the [PAGURE] section which has all the pagure related configurations in it.The section holds the service ID and the repository url's.

+ 

+ +

+ ----

+ [BUGZILLA]

+ BUGZILLA_URL = https://bugzilla.redhat.com

+ ----

+ 

@@ -0,0 +1,4 @@ 

+ [NOTE]

+ ====

+ The --config is a optional command.If not passed it defaults to using the config.ini file from the the repo itself

+ ====

@@ -0,0 +1,29 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: convert

+ 

+ = Convert

+ 

+ Note : The convert functionality is bundled in the accept functionality,indivisual conversion without the accept functionality is still possible.

+ 

+ The convert command converts the issues in to Userstories on taiga. The user can spcify any no of issues to convert at once.The convert functionality not only creates the userstory but also maps all the custom attribtues of the issue to the user stoy. Once the issue is succcesuflly converted to the user story,the issue status is changed to close/processed.

+ 

+ include::config.note.adoc[]

+ 

+ 

+ == Single Conversion

+ 

+ Single Issue conversion example shown below,the "X" is the issue refrence no(the issue no that is seen in the gui) from taiga.

+ 

+ +

+ ----

+ fedora-change-wrangler convert --taiga "X"

+ ----

+ 

+ == Bulk Conversion

+ 

+ Bulk conversion example is shown below, the "X" is the issue refrence no(the issue no is seen in the gui). Multiple issues can thus be converted at once.

+ 

+ +

+ ----

+ fedora-change-wrangler convert --taiga 25 30 45 50

+ ----

@@ -0,0 +1,6 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: bugzilla-dev.adoc

+ 

+ The Current version of the Tool uses the https://github.com/python-bugzilla/python-bugzilla[Python-Bugzilla] to interact with bugzilla as there were too many issues with bugzillas rest api.

+ 

+ One may find more information on the tool at the above link.

@@ -0,0 +1,6 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: config-dev.adoc

+ 

+ The config file is in a .ini format as it is human readable unlike json,yaml and similar ones.

+ 

+ The config file can also be supplied from a user defined location usng the --config flag.The config contains all the required details mostly for taiga as the id's are important.

@@ -0,0 +1,7 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: mailing-list.adoc

+ 

+ The Mailing functionality uses SMTP Multipart.The --reply flag if given in the cli sets the header to reply all to gain this we use a combination of lists and Multipart reply to header.

+ 

+ Note:

+ By defualt wihtout the --reply flag the first id in the config.ini senders list is set in the reply to header and reply to all defaults to just that adress.

@@ -0,0 +1,11 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: pagure-dev.adoc

+ 

+ === Auth

+ As mentioned in the user docs the api keys per repo are stored securly,they keyring module is used for the store of all the keys mapped by their repo name.Due to certain limitation only the fesco and the release docs keys are stored instead of per repo storage which was in a early commit of the tool.

+ 

+ The authorization:token format is used and the tokens/api keys are passed in the header

+ 

+ === Calls & Token

+ All the calls are done via the rest api of pagure and use the requests module to call them.

+ 

@@ -0,0 +1,19 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: taiga.adoc

+ 

+ === Auth

+ Taiga uses a token based auth each request to the api needs the token to be able to function.The token is fetching using the user id and password and then via https://taigaio.github.io/taiga-doc/dist/api.html#auth-normal-login[another call] the token is retrived and stored in the keyring.

+ 

+ === Conversion

+ Since there exists no endpoint for the direct conversion of the issue to user story,it has to be done manually.

+ 1. Fetch the issue with its refrence id.

+ 2. Fetch the Issues custom attributes using the issue id fetched from Step 1.

+ 3. Post the User Story with the issue description retrived using Step 1

+ 4. Post the User Story Custom Attributes Fetched using Step 2.

+ 5. Map the User Story as per the version custom attribute fetched from Step 2 to the respective Epic.

+ 6. Changed the Issue Status to Closed.

+ 

+ === Config Mappings

+ Since taiga uses the ID format to recognize each function,custom attribute and issue the config file contains all the id's for the specifc status's,custom attributes etc

+ 

+ Without these config mappings everything would have to be hardcoded which removes the functionality of having it point to user specific taiga instance.

@@ -0,0 +1,23 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: fesco

+ 

+ = Fesco

+ The fesco command is used to create a issue with all the details of the proposed change and the link to the issue in taiga.The actual fesco repo can be pointed and changed via the config.ini file.

+ 

+ include::config.note.adoc[]

+ 

+ === Create a issue

+ To create a issue the following command would be required below,the "X" is the issue refrence no(the issue no that is seen in the gui) from taiga.

+ 

+ +

+ ----

+ fedora-change-wrangler fesco --fesco "X"

+ ----

+ 

+ === Bulk Creation

+ To create issue in bulk ,below,the "X" is the issue refrence no(the issue no that is seen in the gui) from taiga.

+ 

+ +

+ ---

+ fedora-change-wrangler fesco --fesco 10 20 30 40 50

+ ---

empty or binary file added
@@ -0,0 +1,22 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: list-userstories

+ 

+ = List

+ Listing is a functionality that allows the User to List out all the pending Usestories and Issues,It is configered to list all the Userstories and issues with the new status.

+ 

+ List command prints out the output in the console itslef using ASCII formating and tables for good visuals.

+ The user would be able to see the version no,the subject and the issue no.

+ 

+ === List Issues

+ 

+ To list Issue :

+ +

+ ----

+ fedora-change-wrangeler list issue --pending

+ ----

+ 

+ === List UserStories :

+ +

+ ----

+ fedora-change-wrangeler list Userstories -- pending

+ ----

@@ -0,0 +1,17 @@ 

+ ifdef::context[:parent-context: {context}]

+ :context: sync-status

+ 

+ = Sync

+ Sync-Status command would allow the user to sync the status of the bz to the status of taiga. It fetches the status from bugzilla and updates the appropriate one on the user story in taiga.

+ If the Bugzilla status is Modifies then the taiga user story status would be update to Testable

+ If the Bugzilla status is ON_QA then the Taiga user story status would update to Code_Complete

+ 

+ The Sync command takes the fedora version as a argument which is linked to the epics for more on that you can refer to the link_here[Developer Documentation].

+ 

+ === Sync-Status Bugzilla to Taiga

+ 

+ To sync in the cli the following command has to be used with 32 being the fedora change version it is intended for :

+ +

+ ----

+ fedora-change-wrangler sync-status 32

+ ----

file added
+35
@@ -0,0 +1,35 @@ 

+ 	

+ #!/bin/sh

+ 	

+ 	

+ if [ "$(uname)" == "Darwin" ]; then

+ 	

+     # Running on macOS.

+ 	

+     # Let's assume that the user has the Docker CE installed

+ 	

+     # which doesn't require a root password.

+ 	

+     echo "The preview will be available at http://localhost:8080/"

+ 	

+     docker run --rm -v $(pwd):/antora:ro -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro -p 8080:80 nginx

+ 	

+  

+ 	

+ elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then

+ 	

+     # Running on Linux.

+ 	

+     # Fedora Workstation has python3 installed as a default, so using that

+ 	

+     echo ""

+ 	

+     echo "The preview is available at http://localhost:8080"

+ 	

+     echo ""

+ 	

+     cd ./public

+ 	

+     python3 -m http.server 8080

+ 	

+ fi 

\ No newline at end of file

file added
+40
@@ -0,0 +1,40 @@ 

+   

+ site:

+   

+   title: Fedora Change Wrangler Usage Guide

+   

+   start_page: fedora-change-wrangler::index

+   

+ content:

+   

+   sources:

+   

+    - url: .

+   

+      branches: HEAD

+   

+ ui:

+   

+   bundle:

+   

+     url: https://asamalik.fedorapeople.org/ui-bundle.zip

+   

+     snapshot: true

+   

+   default_layout: with_menu

+   

+ output:

+   

+   clean: true

+   

+   dir: ./public

+   

+   destinations:

+   

+   - provider: archive

+   

+ runtime:

+   

+   pull: true

+   

+   cache_dir: ./cache 

\ No newline at end of file

file added
+46
@@ -0,0 +1,46 @@ 

+ ## Basic usage 

+ 

+ python3.6 main.py auth taiga --token 

+ Refreshes/Fetches new token from taiga

+ 

+ python3.6 main.py auth taiga --reset

+ Resets/Sets the Username and Password in the keyring for taiga

+ 

+ python3.6 main.py auth pagure --whoami

+ To check if pagure can identify you and if token is valid

+ 

+ python3.6 main.py auth pagure --reset 

+ Resets/Sets the Username and Password in the keyring for pagure

+ 

+ python3.6 main.py auth bugzilla --reset

+ Resets/Sets the Username and Password in the keyring for Bugzilla

+ 

+ python3.6 main.py auth email --reset

+ Resets/Sets the Username and Password in the keyring for Email

+ 

+ python3.6 main.py convert --taiga x

+ Converts issue to user story in taiga the "X" stands for the issue refrence no

+ i.e python3.6 main.py convert --taiga 4

+ There can also be multiple issues converted in bulk at once

+ i.e python3.6 main.py convert --taiga 5 10 15 20 25 30 35 40 45 50

+ 

+ python3.6 main.py list issue --pending

+ Lists pending issues from taiga

+ 

+ python3.6 main.py list userstory --pending

+ Lists pending userstory from taiga

+ 

+ python3.6 main.py announce --ml "X" --reply

+ Announces to the mailing list the "X" stands for issue refrence from taiga,--reply if not mentioned has the reply option for all emails,

+ if set only the first email adress is set as reply to in the header

+ 

+ python3.6 main.py fesco --fesco "X"

+ Creates a issue in the fesco repo on pagure. "X" stands for the issue refrence/No from taiga

+ 

+ python3.6 main.py accept --accept "X"

+ Accepts the Change Converts Issue to UserStory creates a Bug in bugzilla

+ "X" stands for issue Refrence/No from taiga

+ 

+ --reply

+ An optional Header if not mentioned has the reply option for all emails,

+ if set only the first email adress is set as reply to in the header

file added
empty or binary file added
file added
+144
@@ -0,0 +1,144 @@ 

+ import os

+ import requests

+ import json

+ import keyring

+ import configparser

+ import editor

+ from tga import epics as tgaepic

+ from tga import issues as tgaissue

+ from tga import userstory as tgauserstory

+ from tga import convert

+ from pgure import issues as pgaissues

+ from bz import bugs as bzbugz

+ from bz import pgba

+ from logger import setup_logging_to_file, log_exception

+ 

+ """

+ def accept(value, configpath):

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['TAIGA']['SERVICE_ID']  # service id

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     for x in value:  # iteratingover name space object

+         try:

+             r = tgaissue.get_issue(x, config)  # x is user story refrence id

+             if r.status_code == 200:

+                 data = json.loads(r.content)

+                 print(data, "this is user story data")

+                 details = data['description']

+                 subject = data['subject']

+                 taiga_issue_id = data['id']

+                 taiga_isssue_ref = data['ref']

+                 taiga_issue_version = data['version']

+                 #fedora_version = data['epics']

+                 owner = data['owner_extra_info']['username']

+                 try:

+                     r = tgaissue.caget_issue(taiga_issue_id, config)

+                     if r.status_code == 200:

+                         data = json.loads(r.content)

+                         summary = data['attributes_values']['11372']

+                         bugzilla_id = data['attributes_values']['11373']

+                         approval_required = data['attributes_values']['11374']

+                         owners = data['attributes_values']['11375']

+                         contingency_deadline = data['attributes_values']['11376']

+                         mass_rebuild = data['attributes_values']['11377']

+                         policy_change = data['attributes_values']['11378']

+                         modifies_deliverables = data['attributes_values']['11379']

+                         system_wide_change = data['attributes_values']['11370']

+                         relengticket = data['attributes_values']['11371']

+                         fedora_version = data['attributes_values']['11383']

+                         print(bugzilla_id)

+                         print("this step")

+                         bzid = list(bugzilla_id.split(', '))

+                         print(bzid)

+                         print(bugzilla_id, " This is bugzilla_id")

+                         try:

+                             taiga_issue_link = str(config['TAIGA']['TAIGA_SITE_ISSUE_URL']) + str(taiga_isssue_ref)

+                             maillist_link = "random"

+                             maillist_dsc_list = "random"

+                             owner = "@" + str(owner)

+                             with open("bugzilla_bug.txt", "w+") as b_txt:

+                                 b_txt.write("{}\n\n*{}\n*{}\n*{}\n*{}\n".format(taiga_issue_link, summary))

+                             editor.edit(filename="bugzilla_bug.txt")

+                             try:

+                                 with open ("bugzilla_bug.txt", "r") as b_txt:

+                                     bug_text = b_txt.read()

+                                 payload = {

+                                             'product': 'Fedora',

+                                             'component': 'Changes Tracking',  # temporary only

+                                             'version': 'rawhide',  

+                                             'summary': subject,

+                                             'description': bug_text,

+                                             'assigned_to': bzid[0],

+                                             'cc': bz_id[1:]

+                                 }

+                                 r = bzbugs.post_bug(payload, config)

+                                 print(r.content, r.status_code) # Development only

+                                 if r.status_code == 200:

+                                     owner = "@" + str(owner)

+                                     with open("rnotes_issue.txt", "w+") as rnotes_txt:

+                                         p_txt.write("{}\n\n*{}\n".format("standard text here", taiga_issue_link))

+                                     editor.edit(filename="rnotes_issue.txt")

+                                     try:

+                                         with open("rnotes_issue.txt", "r") as rnotes_txt:

+                                             issue_text = rnotes_txt.read()

+                                         if system_wide_change == True:

+                                             syschange = "System-Wide Change"

+                                         elif system_wide_change == False:

+                                             syschange = "Change"

+                                         title = "F" + str(fedora_version) + ' ' + str(syschange) + ':' + str(subject)

+                                         payload = {

+                                                     'title' = title,

+                                                     'issue_content': issue_text

+                                         }

+                                         print(title, payload)

+                                         repo = ['PAGURE']['RELEASE_NOTES_REPO']

+                                         r = pgaissues.post_issue(payload, repo, config)

+                                         print(r)

+ """

+ 

+ 

+ def accept(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['TAIGA']['SERVICE_ID']  # service id

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     value = args.issue

+     for x in value:  # iteratingover name space object

+         try:

+             #print(x)

+             """

+             The conversion of X to string below

+             is because to maintin indivual convert

+             functionality.The Convert Functuion

+             needs something it can iterate over

+             to maintain multiple conversion functionality

+             int is not iterable so we convert it to string

+             since with the interation logic in both it only sees

+             it as a single int and we endup

+             """

+             issuel = []

+             issuel.append(x)

+             #print(issuel)

+             userstoryid, conversion = convert.convert(issuel, configpath)

+             if conversion == True:

+                 print("Sucessfully Converted Issue to User story")

+                 bz = pgba.pgtobz(issuel, userstoryid, configpath)

+                 if bz == True:

+                     print("""Sucessfully Created Bugzilla Bug

+                             and issue in release notes """)

+                 else:

+                     print("Error in Bug creation")

+             else:

+                 print("Error in conversion to user story")

+             issuel = False

+             print(issuel)

+         except Exception as e:

+             print(e, "Unable to accept the Change Proposal")

+             log_exception(e)

+ 

file added
+62
@@ -0,0 +1,62 @@ 

+ import requests

+ import configparser

+ import keyring

+ import json

+ import time

+ # import bugzilla as bapi

+ 

+ 

+ def post_bug(createinfo, bzapi, config):

+     #try:

+     """

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     """

+     url = str(config['BUGZILLA']['BUGZILLA_URL']) + "/rest/bug"

+     """

+     headers = {

+         'Content-Type': 'application/json',

+         #'Authorization': '{}'.format(keyring.get_password(config['BUGZILLA']['SERVICE_TOKEN'], "api_token"))

+         # 'Authorization': 'Bearer {0}'.format(str(123))

+         #'X-BUGZILLA-API-KEY': '{}'.format(keyring.get_password(config['BUGZILLA']['SERVICE_TOKEN'], "api_token"))

+         #'Bugzilla_api_key': '{}'.format(keyring.get_password(config['BUGZILLA']['SERVICE_TOKEN'], "api_token"))

+     }

+     """

+     #print(headers)  

+     if not bzapi.logged_in:

+         print("This example requires cached login credentials for %s" % url)

+         bzapi.interactive_login()

+     #print(createinfo)

+     newbug = bzapi.createbug(createinfo)

+     #print(newbug)

+     return newbug

+     print("Created new bug id=%s url=%s" % (newbug.id, newbug.weburl))

+     """

+         url = str(config['BUGZILLA']['BUGZILLA_URL']) + "/rest.cgi/bug?" + "api_key=ZzKzxycfIG42FD1PaEEzJbTiZwCGIoo2GJvkWZGt"#.format(keyring.get_password(config['BUGZILLA']['SERVICE_TOKEN'], "api_token"))

+         print(url)  # debug/dev env only

+         r = requests.post(

+             url,

+             headers=headers,

+             data=json.dumps(payload)

+         )

+         return r

+         """

+     """

+     except requests.exceptions.RequestException as e:

+         print(e)

+     except Exception as e:

+         print(e)

+         return e

+     """

+ def get_bug(bugid, bzapi, config):

+     if not bzapi.logged_in:

+         bzapi.interactive_login()

+     #print(bugid)

+     bug = bzapi.getbug(bugid)

+     return bug

+ """

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "api_key: WChvNU7Z94xuk6adFn4GA8Y8UgcqQyIx5wgLVkbf" \

+ -s https://bugzilla.redhat.com/rest/whoami?

+ """ 

\ No newline at end of file

file added
+56
@@ -0,0 +1,56 @@ 

+ import requests

+ import json

+ import keyring

+ import random

+ import os

+ import binascii

+ import getpass

+ import configparser

+ 

+ from logger import setup_logging_to_file, log_exception

+ 

+ """"

+ config = configparser.ConfigParser()

+ config.read('config.ini')

+ 

+ service_id = config['BUGZILLA']['SERVICE_ID']  # service id

+ service_token = config['BUGZILLA']['SERVICE_TOKEN']  # service d for auth

+ bz_url = config['BUGZILLA']['DEFAULT_BUGZILLA_URL']  # taiga server note

+ custom_bz = config['BUGZILLA']['CUSTOM_BUGZILLA_URL']

+ 

+ """

+ 

+ """

+ bugzilla uses a api key to enable the api acess

+ Currently there is a xml-rpc method to acess

+ That method is going to be deprecated soon

+ Thus the latest method uses API key to acess 

+ the api token.is sued by the modern rest api

+ """

+ 

+ 

+ def reset(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['BUGZILLA']['SERVICE_ID']  # service id

+     service_token = config['BUGZILLA']['SERVICE_TOKEN']  # service d for auth

+     bz_url = config['BUGZILLA']['BUGZILLA_URL']  # taiga server note

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     print("You User Id and password will be securly store in the Keyring")

+     username = input("Enter your user id for bugzilla: ")

+     password = getpass.getpass("Enter your password for bugzilla: ")

+     api_key = getpass.getpass("Enter your bugzilla api token: ")

+     try:

+         keyring.set_password(service_id, "bugzilla_id", username)

+         keyring.set_password(service_id, username, password)

+         keyring.set_password(service_token, "api_token", api_key)

+         username = binascii.hexlify(os.urandom(20))  # randomising username to avoid sneak memory attacks

+         password = binascii.hexlify(os.urandom(20))  # ranomising pass to avoid sneak memory attacks

+         # username = random.choices(string.ascii_uppercase + string.digits, k=random.randint(1,10))

+         # passwd = random.choices(string.ascii_uppercase + string.digits, k=random.randint(1,10)) 

+         print("Password and api key reset succesfully")

+     except (keyring.errors.PasswordSetError, Exception) as e:

+         print("Failed to reset password & api key", e)

+         log_exception(e)

file added
+170
@@ -0,0 +1,170 @@ 

+ import os

+ import requests

+ import json

+ import keyring

+ import configparser

+ import editor

+ import bugzilla

+ 

+ from tga import epics as tgaepic

+ from tga import issues as tgaissue

+ from tga import userstory as tgauserstory

+ from pgure import issues as pgaissues

+ from bz import bugs as bzbugs

+ from logger import setup_logging_to_file, log_exception

+ 

+ 

+ 

+ def pgtobz(value, userstoryid, configpath):

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['TAIGA']['SERVICE_ID']  # service id

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     URL = config['BUGZILLA']['BUGZILLA_URL']

+     bzapi = bugzilla.Bugzilla(URL)

+     for x in value:  # iteratingover name space object

+         try:

+             issueurl, r = tgaissue.get_issue(x, config)  # x is user story refrence id

+             #print(r)

+             if r.status_code == 200:

+                 data = json.loads(r.content)

+                 #print(data, "this is user story data")

+                 details = data['description']

+                 subject = data['subject']

+                 taiga_issue_id = data['id']

+                 taiga_isssue_ref = data['ref']

+                 taiga_issue_version = data['version']

+                 #fedora_version = data['epics']

+                 owner = data['owner_extra_info']['username']

+                 try:

+                     r = tgaissue.caget_issue(taiga_issue_id, config)

+                     if r.status_code == 200:

+                         data = json.loads(r.content)

+                         summary = data['attributes_values']['11372']

+                         bugzilla_id = data['attributes_values']['11373']

+                         approval_required = data['attributes_values']['11374']

+                         owners = data['attributes_values']['11375']

+                         contingency_deadline = data['attributes_values']['11376']

+                         mass_rebuild = data['attributes_values']['11377']

+                         policy_change = data['attributes_values']['11378']

+                         modifies_deliverables = data['attributes_values']['11379']

+                         system_wide_change = data['attributes_values']['11370']

+                         relengticket = data['attributes_values']['11371']

+                         fedora_version = data['attributes_values']['11383']

+                         #print(bugzilla_id)

+                         #print("this step")

+                         bzid = list(bugzilla_id.split(', '))

+                         #print(bzid)

+                         #print(bugzilla_id, " This is bugzilla_id")

+                         try:

+                             taiga_issue_link = str(config['TAIGA']['TAIGA_SITE_ISSUE_URL']) + str(taiga_isssue_ref)

+                             maillist_link = "random"

+                             maillist_dsc_list = "random"

+                             owner = "@" + str(owner)

+                             with open("bugzilla_bug.txt", "w+") as b_txt:

+                                 b_txt.write("{}\n\n{}\n".format(taiga_issue_link, summary))

+                             editor.edit(filename="bugzilla_bug.txt")

+                             try:

+                                 with open("bugzilla_bug.txt", "r") as b_txt:

+                                     bug_text = b_txt.read()

+                                 """

+                                 payload = {

+                                             'product': 'Fedora',

+                                             'component': 'Changes Tracking',  # temporary only

+                                             'version': 'rawhide',  

+                                             'summary': subject,

+                                             'description': bug_text,

+                                             'assigned_to': bzid[0],

+                                             'cc': bzid[1:]

+                                             #'api_key': '{}'.format(keyring.get_password(config['BUGZILLA']['SERVICE_TOKEN'], "api_token"))

+                                 }

+                                 """

+ 

+                                 createinfo = bzapi.build_createbug(

+                                     product="Fedora",

+                                     version="rawhide",

+                                     component="Changes Tracking",

+                                     summary=subject,

+                                     description=bug_text,

+                                     assigned_to=bzid[0],

+                                     cc=bzid[1:]

+                                     )

+                                 bug = bzbugs.post_bug(createinfo, bzapi, config)

+                                 #print(r.content, r.status_code) # Development only

+                                 #if r.status_code == 200:

+                                 print("Sucessful Bugzilla Bug Creation")

+                                 owner = "@" + str(owner)

+                                 with open("rnotes_issue.txt", "w+") as rnotes_txt:

+                                     rnotes_txt.write("{}\n\n[Change Proposal]({})\n\n {}".format("standard text here", taiga_issue_link, owner))

+                                 editor.edit(filename="rnotes_issue.txt")

+                                 try:

+                                     with open("rnotes_issue.txt", "r") as rnotes_txt:

+                                         issue_text = rnotes_txt.read()

+                                     if system_wide_change == True:

+                                         syschange = "System-Wide Change"

+                                     elif system_wide_change == False:

+                                         syschange = "Change"

+                                     title = "F" + str(fedora_version) + ' ' + str(syschange) + ':' + str(subject)

+                                     payload = {

+                                                 'title': title,

+                                                 'issue_content': issue_text

+                                     }

+                                     #print(title, payload)

+                                     repo = config['PAGURE']['RELEASE_NOTES_REPO']

+                                     r = pgaissues.post_issue(payload, repo, config)

+                                     #print(r)

+                                     if r.status_code == 200:

+                                         print("Sucessful creation of issue on pagure release notes")

+                                         return True

+                                         payload = {

+                                             "attributes_values": {

+                                                 config['TAIGA']['USERSTORY_CA_BUGZILLA_TRACKER']: bug.weburl,

+                                             },

+                                             "version": 2

+                                         }

+                                         r = tgauserstory.post_usca(payload, userstoryid, config)

+                                         if r.status_code == 201:

+                                             print("Sucessfully mapped bz to user story")

+                                         else:

+                                             print("check logs for errors")

+                                     else:

+                                         print("failed to complete acceptance")

+                                 except requests.exceptions.RequestException as e:

+                                     print("Failed to fetch attributes of the issue")

+                                     print(e)

+                                     log_exception(e)

+                                 except Exception as e:

+                                     print(e)

+                                     log_exception(e)

+                             except requests.exceptions.RequestException as e:

+                                 print("Failed to fetch attributes of the issue")

+                                 print(e)

+                                 log_exception(e)

+                             except Exception as e:

+                                 print(e)

+                                 log_exception(e)

+                         except requests.exceptions.RequestException as e:

+                             print("Failed to fetch attributes of the issue")

+                             print(e)

+                             log_exception(e)

+                         except Exception as e:

+                             print(e)

+                             log_exception(e)

+                     else:

+                         print("Cant fetch attributes from Taiga")

+                 except requests.exceptions.RequestException as e:

+                     print("Failed to fetch attributes of the issue")

+                     print(e)

+                     log_exception(e)

+                 except Exception as e:

+                     print(e)

+                     log_exception(e)

+         except requests.exceptions.RequestException as e:

+             print("Failed to fetch attributes of the issue")

+             print(e)

+             log_exception(e)

+         except Exception as e:

+             print(e)

+             log_exception(e)     

+ 

file added
+94
@@ -0,0 +1,94 @@ 

+ [TAIGA]

+ SERVICE_ID = taiga

+ SERVICE_TOKEN = taiga_auth

+ PROJECT_ID = 325667 

+ TAIGA_URL = https://api.taiga.io

+ TAIGA_SITE_ISSUE_URL = https://tree.taiga.io/project/pac_23-test-changes-tracker-kanban/issue/

+ 

+ PROJECT_WEB_URL = https://tree.taiga.io/project/

+ PROJECT_WEB_NAME = pac_23-test-changes-tracker-kanban

+ 

+ ISSUE_STATUS_NEW = 254

+ ISSUE_STATUS_NEEDS_INFO = 255

+ ISSSUE_STATUS_ACCEPTED = 295

+ ISSUE_STATUS_ANNOUNCED = 258

+ ISSUE_STATUS_READY_FOR_WRANGLER = 256

+ ISSUE_STATUS_READY_FOR_FESCO = 259

+ ISSUE_STATUS_PROCESSED = 257

+ USERSTORY_STATUS_NEW = 235

+ USERSTORY_STATUS_ANNOUNCED = 267

+ USERSTORY_STATUS_R_FESCO = 266

+ USERSTORY_STATUS_ACCEPTED = 231

+ USERSTORY_STATUS_ARCHIVED = 232

+ USERSTORY_STATUS_CODE_COMPLETE = 233

+ USERSTORY_STATUS_TESTABLE = 234

+ 

+ ISSUE_CA_SYSTEM_WIDE_CHANGE = 18

+ ISSUE_CA_SUMMARY = 20

+ ISSUE_CA_BUGZILLA_CONTACT = 21

+ ISSUE_CA_RELENG_TICKET = 19

+ ISSUE_CA_TRADEMARK_APPROVAL = 22

+ ISSUE_CA_OWNERS = 23

+ ISSUE_CA_FESCO_TICKET = 30

+ ISSUE_CA_BUGZILLA_TRACKER = 31

+ ISSUE_CA_RELEASE_NOTES = 32

+ ISSUE_CA_CONTINGENCY = 24

+ ISSUE_CA_MASS_REBUILD = 25

+ ISSUE_CA_POLICY_CHANGE = 26

+ ISSUE_CA_MODIFIES_DELIVERABLES = 27

+ ISSUE_CA_VERSION = 28

+ ISSUE_CA_USERSTORY_LINK = 29

+ USERSTORY_CA_SYSTEM_WIDE_CHANGE = 24

+ USERSTORY_CA_SUMMARY = 25

+ USERSTORY_CA_BUGZILLA_CONTACT = 26

+ USERSTORY_CA_RELENG_TICKET = 27

+ USERSTORY_CA_TRADEMARK_APPROVAL = 28

+ USERSTORY_CA_OWNERS = 29

+ USERSTORY_CA_FESCO_TICKET = 30

+ USERSTORY_CA_BUGZILLA_TRACKER = 31

+ USERSTORY_CA_RELEASE_NOTES = 32

+ USERSTORY_CA_CONTINGENCY = 33

+ USERSTORY_CA_MASS_REBUILD = 34

+ USERSTORY_CA_POLICY_CHANGE = 35

+ USERSTORY_CA_MODIFIES_DELIVERABLES = 26

+ USERSTORY_CA_ISSUE_LINK = 37

+ 

+ ISSUE_PRIORITIES_LOW = 979360

+ ISSUE_PRIORITIES_NORMAL = 979361

+ ISSUE_PRIORITIES_HIGH = 979362

+ 

+ ISSUE_SERVITY_WISHLIST = 1627044

+ ISSUE_SERVITY_MINOR = 1627045

+ ISSUE_SERVITY_NORMAL = 1627046

+ ISSUE_SERVITY_IMPORTANT = 1627047

+ ISSUE_SERVITY_CRITICAL = 1627048

+ 

+ ISSUE_TYPE_BUG = 983893

+ ISSUE_TYPE_QUESTION = 983894

+ ISSUE_TYPE_ENHANCEMENT = 983895

+ 

+ [PAGURE]

+ SERVICE_ID = pagure

+ API_URL = https://pagure.io/api/0/

+ FESCO_REPO = fedora-change-wrangler

+ RELEASE_NOTES_REPO = Test-for-Release-Notes

+ 

+ [BUGZILLA]

+ SERVICE_ID = bugzilla

+ SERVICE_TOKEN = bugzilla_auth

+ PROJECT_ID = 315827 # for test only 

+ BUGZILLA_URL = https://bugzilla.redhat.com/xmlrpc.cgi

+ ; TEST = no

+ 

+ [EMAIL]

+ SERVICE_ID = email

+ #SENDER_EMAIL_ID = manasmangaonkar@gmail.com

+ LIST: ["bcotton@funnelfiasco.com","bcotton@redhat.com"]

+ ; LIST: [devel@lists.fedoraproject.org,devel-announce@lists.fedoraproject.org]

+ PORT = 465

+ SMTP_SERVER = smtp.gmail.com

+ ; TEST = yes

+ ; 1892835

+ 

+ [LOG]

+ LOCATION = "main.log" 

\ No newline at end of file

file added
+118
@@ -0,0 +1,118 @@ 

+ import smtplib

+ import ssl

+ import requests

+ import configparser

+ import json

+ import keyring

+ import tga

+ import email.mime.multipart

+ import editor

+ 

+ from mail import maillist

+ from tga import issues

+ from logger import setup_logging_to_file, log_exception

+ 

+ 

+ """

+ service_id = config['EMAIL']['SERVICE_ID']  # service id

+ # service_token = config['']['SERVICE_TOKEN']

+ #pid = config['TAIGA']['PID']

+ if config['EMAIL']['TEST'] == 'yes':

+     sender = config['EMAIL']['CUSTOM_EMAIL_ID']

+     reciver = config['EMAIL']['TEST_LIST']

+ elif config['EMAIL']['TEST'] == 'no':

+     sender = config['EMAIL']['DEFAULT_EMAIL_ID]

+     receiver = config['EMAIL']['LIST']

+ else:

+     print("please set proper test status in config")

+ 

+ 

+ def email_send(issueno):

+     port = config['EMAIL']['PORT']  # For SSL

+     smtp_server = config['EMAIL']['SMTP_SERVER']

+     sender_email = sender  # Enter your address

+     receiver_email = reciver  # Enter receiver address

+     data = tga.userstory.get(issueno)

+     try:

+         msg = email.mime.multipart.MIMEMultipart()

+         msg['to'] = reciver

+         msg['from'] = sender

+         msg['subject'] = data['subject']

+         msg.add_header('reply-to', reciver_email[0])

+         msg.attach(MIMEText(body, data['description']))

+         # This message is sent from Python."""

+ """

+         context = ssl.create_default_context()

+         with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:

+             server.login(sender_email, password)

+             server.sendmail(sender_email, receiver_email, message)

+ """

+ 

+ 

+ def mails(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['EMAIL']['SERVICE_ID']

+     sender = config['EMAIL']['SENDER_EMAIL_ID']

+     reciver = config['EMAIL']['LIST']

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     #print(args)

+     value = args.ml

+     for x in value:

+         #for x in value:

+            #ref = input("input the issue no you want to announce: ")

+         try:

+             #print(x)

+             r = issues.get_issue(x, config)

+             if r.status_code == 200:

+                 data = json.loads(r.content)

+                 issue_id = data['id']

+                 issue_version = data['version']

+                 print(data)

+                 try:

+                     ra = issues.caget_issue(issue_id, config)

+                     if ra.status_code == 200:

+                         cadata = json.loads(ra.content)

+                         """

+                         body = '''\

+                         == Summary ==

+                         {}

+                         == Owners == 

+                         {}

+                         == Detailed Description == \

+                         '''.format(cadata['attributes_values']['11372'], cadata['attributes_values']['11375'], data['description'])

+                         """

+                         with open("mail.txt", "w+") as m_txt:

+                             m_txt.write("== Summary == \n{}\n\n== owner == \n{}\n\n== Detailed Description == \n{}".format(cadata['attributes_values']['11372'], cadata['attributes_values']['11375'], data['description']))

+                             # m_txt.write("{}".format(body))

+                         editor.edit(filename="mail.txt")

+                         try:

+                             subject = str(cadata['attributes_values']['11383']) + ":" + str(data['subject'])

+                             mailstatus = maillist.email_send(subject, args.reply, config)

+                             if mailstatus == True:

+                                 payload = {

+                                             'status': config['TAIGA']['ISSUE_STATUS_ANNOUNCED'],

+                                             'version': issue_version

+                                 }

+                                 r = tgaissue.changestatus_issue(issue_id, payload, config)

+                                 if r.status_code == 201:

+                                     print("Sucessfully changed status to announced")

+                                 else:

+                                     print("Unable to Change issue status")

+                             else:

+                                 print("Mail was not sent check logs for errors")

+                         except Exception as e:

+                             print(e)

+                             log_exception(e)

+                     else:

+                         print("check logs")

+                 except requests.exceptions.RequestException as e:

+                     print(e)

+                     log_exception(e)

+             else:

+                 print("unable to send emails check logs")

+         except requests.exceptions.RequestException as e:

+             print(e)

+             log_exception(e)

file added
+32
@@ -0,0 +1,32 @@ 

+ import keyring

+ import os

+ import getpass

+ import configparser

+ import binascii

+ 

+ from logger import setup_logging_to_file, log_exception

+ """

+ config = configparser.ConfigParser()

+ config.read('config.ini')

+ 

+ service_id = config['EMAIL']['SERVICE_ID']

+ """

+ 

+ 

+ def reset(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['EMAIL']['SERVICE_ID']

+     print("You User Id and password will be securly store in the Keyring")

+     username = input("Enter your id: ")

+     password = getpass.getpass("Enter your password for email: ")

+     try:

+         keyring.set_password(service_id, "email_username", username)  # refer line 67

+         keyring.set_password(service_id, username, str(password))

+         username = binascii.hexlify(os.urandom(20))  # randomising username to avoid sneak memory attacks

+         password = binascii.hexlify(os.urandom(20))  # ranomising pass to avoid sneak memory attacks

+         print("Password reset succesfully")

+     except (keyring.errors.PasswordSetError, Exception) as e:

+         print("Failed to reset password", e)

+         log_exception(e)

file added
+94
@@ -0,0 +1,94 @@ 

+ import smtplib

+ import ssl

+ import configparser

+ import json

+ import keyring

+ import tga

+ import email.mime.multipart

+ 

+ from email import encoders

+ from email.mime.base import MIMEBase

+ from email.mime.multipart import MIMEMultipart

+ from email.mime.text import MIMEText

+ from logger import setup_logging_to_file, log_exception

+ """

+ config = configparser.ConfigParser()

+ config.read('config.ini')

+ """

+ 

+ # service_token = config['']['SERVICE_TOKEN']

+ # pid = config['TAIGA']['PID']

+ """

+ if config['EMAIL']['TEST'] == 'yes':

+     sender = config['EMAIL']['CUSTOM_EMAIL_ID']

+     reciver = config['EMAIL']['TEST_LIST']

+ elif config['EMAIL']['TEST'] == 'no':

+     sender = config['EMAIL']['DEFAULT_EMAIL_ID']

+     reciver = config['EMAIL']['LIST']

+ else:

+     print("please set proper test status in config")

+ """

+ 

+ 

+ def email_send(subject, replyto, config):

+     """

+     config = configparser.ConfigParser()

+     config.read('config.ini')

+     """

+     service_id = config['EMAIL']['SERVICE_ID']  # service id

+     port = config['EMAIL']['PORT']  # For SSL

+     smtp_server = config['EMAIL']['SMTP_SERVER']

+     sender = config['EMAIL']['SENDER_EMAIL_ID']

+     reciver = config['EMAIL']['LIST']

+     sender_email = sender  # Enter your address

+     """

+     awesome because it does automatically "cast" values

+     for no's remove the "" in list 

+     https://stackoverflow.com/questions/335695/lists-in-configparser

+     The answer below the selected/chosen answer

+     """

+     reciver_emaillist = json.loads(config.get("EMAIL", "LIST"))

+     #print(type(reciver_emaillist))

+     #reciver_email = ['manas.man95@gmail.com', 'ttim3886@gmail.com']

+     #reciver_email = reciver_email.split(',')

+     reciver_email = ', '.join(reciver_emaillist)

+     #reciver_email = reciver

+     #print(type(reciver_email))

+     #print(reciver_email)

+     #reciver_email = ', '.join(reciver)

+     #print(reciver_email)  # Enter receiver address

+     """

+     Basically what is being done is we use the list to refer by id

+     for the header as the converted string if refrenced by id

+     i.e reciver_email[0] would return the first character of the string

+     Thus the reciver_emaillist parameter is used below in the reply header

+     to refer the first one in the string

+     """

+     username = keyring.get_password(service_id, "email_username")

+     password = keyring.get_password(service_id, username)

+     #print(password, "this is pass")

+     try:

+         msg = MIMEMultipart()

+         msg['To'] = reciver_emails

+         msg['From'] = username

+         msg['Subject'] = subject

+         #print("this step")

+         if replyto == True:

+             msg.add_header('reply-to', reciver_email)

+         elif replyto == False:

+             msg.add_header('reply-to', reciver_emaillist[0])

+         with open("mail.txt", "r") as m_text:

+             data = m_text.read()#.replace('\n', '')

+         #print(data)

+         msg.attach(MIMEText(data, "plain"))

+         # This message is sent from Python."""

+         context = ssl.create_default_context()  

+         with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:

+             server.login(sender_email, password)

+             server.sendmail(sender_email, reciver_email, msg.as_string())

+             #server.send_message(msg)

+         print("succesfully sent email")

+         return True

+     except Exception as e:

+         print(e)

+         log_exception(e)

file modified
+252 -20
@@ -4,19 +4,38 @@ 

  import json

  import argparse

  import sys

- from auth import tauth

- # import taiga

- from convert import convert

+ import accept

+ import update

  

+ from tga import taiga_auth

+ from pgure import pagure_auth

+ from bz import bugzilla_auth

+ from tga import issues as tgaissue

+ from tga import userstory as tguserstory

+ from tga import convert

+ from tga import createprop

+ from mail import climail

+ from mail import mailauth

+ from pgure import fesco

+ from logger import setup_logging_to_file, log_exception

  

  class Change_Tool(object):

      def __init__(self):

          parser = argparse.ArgumentParser(

              description='Cli for Change Tool',

-             usage='''change-tool <command> [<args>]'''

-             )

+             usage='''fedora-change-wrangler <command> [<args>]

  

-         parser.add_argument('command', help='Subcommand to run')

+ The commands are:

+     auth    Authenticates with Bugzilla,Taiga and Pagure

+     convert Converts the Taiga issues to user stories

+     list    Lists the Pending issues/userstory as per the optinal argument

+     announce Announces to the mailing list of the approved change

+     fesco    Creates issues on the fesco repo with details from the approved change proposal

+     accept   Accepts the Change Proposal by Converting issue to user story and creates a tracking bug in Bugzilla 

+     sync     Syncs the tracking bug status with Taiga status

+     --help   Lists out the subcommand in each subcommand of the cli

+ ''')

+         parser.add_argument('command', help='Subcommand --flags')

          # parse_args defaults to [1:] for args, but you need to

          # exclude the rest of the args too, or validation will fail

          args = parser.parse_args(sys.argv[1:2])
@@ -30,44 +49,257 @@ 

      def auth(self):

          parser = argparse.ArgumentParser(

              description='Module for authentication functions')

-         parser.add_argument('--auth', help='runs the auth instance')

+         # parser.add_argument('--auth', help='runs the auth instance')

          subparsers = parser.add_subparsers(dest='command', help='sub-command help')

  

          # Subparser for taiga

          taiga = subparsers.add_parser('taiga', help='taiga auth module')

          taiga.add_argument('--token', action='store_true', help='refreshes the token')

-         taiga.add_argument('--reset', action='store_true', help='resets the user id and pass')

+         taiga.add_argument('--reset', action='store_true', help='sets/resets the user id and pass')

  

          # subparser for pagure

          pagure = subparsers.add_parser('pagure', help='pagure auth module')

-         pagure.add_argument('--token', action='store_true', help='refreshes the token')

-         pagure.add_argument('--reset', action='store_true', help='resets the user id and pass')

+         pagure.add_argument('--whoami', action='store_true', help='returns who the user is,for debug/developement only')

+         pagure.add_argument('--reset', action='store_true', help='resets the pagure token')

  

          # subparser for bugzilla

          bugzilla = subparsers.add_parser('bugzilla', help='bugzilla auth module')

-         bugzilla.add_argument('--token', action='store_true', help='refreshes the token')

-         bugzilla.add_argument('--reset', action='store_true', help='resets the user id and pass')

+         bugzilla.add_argument('--token', action='store_true', help='sets the the token for bugzilla')

+         bugzilla.add_argument('--reset', action='store_true', help='sets/resets the user id,pass and the api token')

+         

+         email = subparsers.add_parser('email', help='email auth module')

+         email.add_argument('--reset', action='store_true', help='sets/resets teh email adress')

+         parser.add_argument('--config',

+                             #dest='configpath',

+                             #action='store',

+                             #type=string,

+                             default='config.ini',

+                             help='Sets config path')

          args = parser.parse_args(sys.argv[2:])

-         if args.auth:

-             print("Incomplete command,please specify the auth")

+         configpath = args.config

+         print(configpath) # debug only

+         print(args) # debug only

+         # print(args) # debug only

          if args.command == 'taiga':

              if args.token:

-                 tauth.refresh_token()

+                 taiga_auth.refresh_token(args)

              elif args.reset:

-                 tauth.reset()

+                 taiga_auth.reset(args)

+             else:

+                 print("Wrong command")

+                 print(parser.print_help())

+         elif args.command == 'pagure':

+             if args.reset:

+                 pagure_auth.reset(args)

+             else:

+                 print("Wrong command")

+                 print(parser.print_help())

+         elif args.command == 'bugzilla':

+             if args.token:

+                 bugzilla_auth.refresh_token(args)

+             elif args.reset:

+                 bugzilla_auth.reset(args)

+             else:

+                 print("Wrong command,please check documentation for the proper command")

+                 print(parser.print_help())

+         elif args.command == 'email':

+             if args.reset:

+                 mailauth.reset(args)

+             else:

+                 print("Wrong Command check documentation")

+                 print(parser.print_help())

+         else:

+             print("Please Check the Documentation for the proper command or press --h for help")

+             print(parser.print_help())

+ 

          # print("Running the auth instance.....")

          # authenticate()

- 

+     

      def convert(self):

+         """

+         Convert is the only module

+         that has directly mapped args to the module

+         as we want to maintain the ability to use

+         the convert functionality on its own and

+         the way the multi[ple conversion is

+         structured,prevents passing just the args

+         as a whole.

+         """

          parser = argparse.ArgumentParser(

              description='converts taiga issue to user story')

          parser.add_argument('--taiga',

                              nargs='+',

                              type=int,

-                             help="Converts Issue to User Story")

+                             help='Converts Issue to User Story')

+         parser.add_argument('--config',

+                             #dest='configpath',

+                             #action='store',

+                             #type=string,

+                             default='config.ini',

+                             help='Sets config path')

+         args = parser.parse_args(sys.argv[2:])

+         configpath = args.config

+         print(configpath)  # Debug only

+         print(args)  # debug only

+         if args.command == 'taiga':

+             convert.convert(args.taiga, args.config)

+         elif args.command == 'help':

+             print(parser.print_help())

+         else:

+             print("Wrong Command")

+             print(parser.print_help())

+ 

+     def list(self):

+         parser = argparse.ArgumentParser(

+             description='announces to mailing list')

+         #parser.add_argument('--list', help='runs the auth instance')

+         subparsers = parser.add_subparsers(dest='command', help='sub-command help')

+ 

+         # list issues

+         issue = subparsers.add_parser('issue', help='Lists issues')

+         issue.add_argument('--pending', action='store_true', help='lists all the pending issues')

+ 

+         userstory = subparsers.add_parser('userstory', help='Lists user stories')

+         userstory.add_argument('--pending', action='store_true', help='lists pending users stories')

+         parser.add_argument('--config',

+                             #action='store',

+                             #type=string,

+                             #dest='configpath',

+                             default='config.ini',

+                             #required=False,

+                             help='Sets config path')

+         args = parser.parse_args(sys.argv[2:])

+         if args.command == 'issue':

+             if args.pending:

+                 tgaissue.list_issue(args)

+             else:

+                 print("wrong command")

+         elif args.command == 'userstory':

+             if args.pending:

+                 tguserstory.list_us(args)

+             else:

+                 print("Wrong command")

+         else:

+             print("wrong command")

+ 

+     def announce(self):

+         parser = argparse.ArgumentParser(

+             description='announces to mailing list')

+         parser.add_argument('--ml',

+                             nargs='+',

+                             type=int,

+                             help='Announces to Mailing list')

+         parser.add_argument('--reply',

+                             #nargs='+',

+                             action='store_true',

+                             help="""Option to set reply to header

+                             if not set defaults reply to all recivers

+                             listed in config""")

+         parser.add_argument('--config',

+                             #dest='configpath',

+                             #action='store',

+                             #type=string,

+                             default='config.ini',

+                             help='Sets config path')

+         args = parser.parse_args(sys.argv[2:])

+         configpath = args.config

+         print(configpath)

+         #print(args)

+         print(args.reply)

+         # print(args) # debug only

+         #climail.mails(args.ml, args.reply, args.config)

+         climail.mails(args)

+ 

+     def fesco(self):

+         parser = argparse.ArgumentParser(

+             description='Creates a Issue on fesco repo on pagure')

+         parser.add_argument('--fesco',

+                             nargs='+',

+                             type=int,

+                             help='Announces to Fesco')

+         parser.add_argument('--config',

+                             #dest='configpath',

+                             #action='store',

+                             #type=string,

+                             default='config.ini',

+                             help='Sets config path')

+         args = parser.parse_args(sys.argv[2:])

+         configpath = args.config

+         print(configpath)

+         print(args)

+         # print(args) # debug only

+         #fesco.fesissue(args.fesco, args.config)

+         fesco.fesissue(args)

+     

+     def accept(self):

+         parser = argparse.ArgumentParser(

+             description='announces to mailing list')

+         parser.add_argument('--issue',

+                             nargs='+',

+                             type=int,

+                             #description='Issue No',

+                             help='Accepts the taiga change propsal issue')

+         parser.add_argument('--config',

+                             #dest='configpath',

+                             #action='store',

+                             #type=string,

+                             default='config.ini',

+                             help='Sets User Defined Config path')

+         args = parser.parse_args(sys.argv[2:])

+         #configpath = args.config

+         #print(configpath)

+         #print(args)

+         #print(args.reply)

+         # print(args) # debug only

+         #accept.accept(args.accept, args.config)

+         accept.accept(args)

+ 

+     def update(self):

+         parser = argparse.ArgumentParser(

+             description='Syncing Between Bugzilla and Taiga')

+ 

+         parser.add_argument('--release',

+                             nargs='+',

+                             type=int,

+                             help='Syncing between bugzilla and taiga')

+ 

+         parser.add_argument('--config',

+                             #dest='configpath',

+                             #action='store',

+                             #type=string,

+                             default='config.ini',

+                             help='Sets config path')

+         args = parser.parse_args(sys.argv[2:])

+         #update.sync(args)

+         update.update(args)

+ 

+     def create(self):

+         parser = argparse.ArgumentParser(

+             description='File a Change proposal from the cli')

+         parser.add_argument('--config',

+                             default='config.ini',

+                             help='Sets config path')

          args = parser.parse_args(sys.argv[2:])

-         # print(args)  # Debug only

-         convert(args)

+         createprop.create(args)

+ 

+     """

+     def config(self):

+         parser = argparse.ArgumentParser(

+             description='sets the user defined config')

+         parser.add_argument('--config',

+                             action='store',

+                             type='string',

+                             dest='configPath',

+                             default='"%s/config.ini" % (expanduser("~))',

+                             help='configPath is set')

+ 

+         args = parser.parse_args(sys.argv[2:])

+     """

+     """

+     def accept(self):

+         parser = argparse.ArgumentParser(

+             description='accepts the proposal and pushes to bugzilla')

+     """

  

  

  if __name__ == "__main__":

file added
+104
@@ -0,0 +1,104 @@ 

+ status actual and testinstance 

+ New: , 1892834

+ Announced: 29 ,  1892835

+ Ready for fesco: 30 , 1892836

+ Accepted:  31 , 1892837

+ Archived: 32, 1892838

+ Code Complete: 33 , 1892839

+ Testable: 34 , 1951329

+ 

+ Taiga api returns no's instead of the actual names/description

+ The below no's stand for changes tracker fesco,change-wrangler

+ 1 : System-wide change

+ 2 : Summary

+ 3 : Bugzilla id

+ 4 : Missing

+ 5 : Trademark approval required

+ 6 : Owners

+ 7 : Rel-eng ticket/Rel-end impact ticket

+ 11 : Contingencry deadline

+ 12 : Mass rebuild required

+ 13 : Policy change required

+ 14 : Modifies deliverables

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s https://teams-api.fedoraproject.org/api/v1/issues/by_ref?ref=5\&project=5

+ -s https://teams-api.fedoraproject.org/api/v1/issues/custom-attributes-values/{26}

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s https://teams-api.fedoraproject.org/api/v1/issues/custom-attributes-values/{26}

+ 

+ Get List of Multiple ready for wrangler changes. 

+ curl -X GET -H "Content-Type: application/json" -H "Authorizion: Bearer ${AUTH_TOKEN}" -s https://teams-api.fedoraproject.org/api/v1/userstories?project=5\&status=30

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s https://api.taiga.io/api/v1/issues/custom-attributes-values/{26}

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s http://localhost:8000/api/v1/issue-statuses?project=325667

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s http://api.taiga.io/api/v1/userstory-statuses?project=325667

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s https://api.taiga.io/api/v1/userstory-custom-attributes?project=325667

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s https://api.taiga.io/api/v1/api/v1/issue-custom-attributes?project=325667

+ 

+ 

+ curl -X POST \

+ -H "Content-Type: application/json" \

+ -d '{

+         "subject": "test change",

+         "description": "test new change"

+     }' \

+ -s http://api.taiga.io/api/v1/userstories

+ 

+ "auth_token": "eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hY9LV:FaxXO5XP09sQHyLm7xjGFMa6UmE

+ 

+ push to commit issues,

+ 

+ curl -X POST \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hX0Sw:X9sKb5jHiUDE0Hayfx9YziCDuPw}" \

+ -d '{

+         "project": 1,

+         "subject": "Customer personal data"

+     }' \

+ -s http://localhost:8000/api/v1/userstories

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s http://localhost:8000/api/v1/issues/custom-attributes-values/1232291

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s http://api.taiga.io/api/v1/issues/1232291

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s http://api.taiga.io/api/v1/issues/by_ref?ref=4\&project=1232291

+ 

+ 

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s https://api.taiga.io/api/v1/epics?project=325667 

\ No newline at end of file

file added
+114
@@ -0,0 +1,114 @@ 

+ import os

+ import requests

+ import json

+ import keyring

+ import configparser

+ import editor

+ from tga import epics as tgaepic

+ from tga import issues as tgaissue

+ from tga import userstory as tgauserstory

+ from pgure import issues as pgaissues

+ from logger import setup_logging_to_file, log_exception

+ 

+ """

+ if config['TAIGA']['TEST'] == 'yes':

+     taiga_url = config['TAIGA']['CUSTOM_TAIGA_URL']

+ elif config['TAIGA']['TEST'] == 'no':

+     taiga_url = config['TAIGA']['DEFAULT_TAIGA_URL']

+ else:

+     print("please set test status in config")

+ """

+ 

+ 

+ def fesissue(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['TAIGA']['SERVICE_ID']  # service id

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     value = args.fesco

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     for x in value:  # iteratingover name space object

+         try:

+             r = tgaissue.get_issue(x, config)  # x is user story refrence id

+             if r.status_code == 200:

+                 data = json.loads(r.content)

+                 #print(data, "this is user story data")

+                 details = data['description']

+                 subject = data['subject']

+                 taiga_issue_id = data['id']

+                 taiga_isssue_ref = data['ref']

+                 taiga_issue_version = data['version']

+                 #fedora_version = data['epics']

+                 owner = data['owner_extra_info']['username']

+                 try:

+                     r = tgaissue.caget_issue(taiga_issue_id, config)

+                     if r.status_code == 200:

+                         data = json.loads(r.content)

+                         summary = data['attributes_values']['11372']

+                         bugzilla_id = data['attributes_values']['11373']

+                         approval_required = data['attributes_values']['11374']

+                         owners = data['attributes_values']['11375']

+                         contingency_deadline = data['attributes_values']['11376']

+                         mass_rebuild = data['attributes_values']['11377']

+                         policy_change = data['attributes_values']['11378']

+                         modifies_deliverables = data['attributes_values']['11379']

+                         system_wide_change = data['attributes_values']['11370']

+                         relengticket = data['attributes_values']['11371']

+                         fedora_version = data['attributes_values']['11383']

+                         #print("this step")

+                         bzid = list(bugzilla_id.split(', '))

+                         #print(bzid)

+                         #print(bugzilla_id, " This is bugzilla_id")

+                         try:

+                             taiga_issue_link = str(config['TAIGA']['TAIGA_SITE_ISSUE_URL']) + str(taiga_isssue_ref)

+                             maillist_link = "random"

+                             maillist_dsc_list = "random"

+                             owner = "@" + str(owner)

+                             with open("fesco_issue.txt", "w+") as pg_txt:

+                                 pg_txt.write("{}\n\n * [Change Proposal]({})\n * [devel-announce post]({})\n * [devel list discussion]({})\n * [Rel eng Proposal]({})\n * owner:{}\n".format(summary, taiga_issue_link, maillist_link, maillist_dsc_list, relengticket ,owner))

+                             editor.edit(filename="fesco_issue.txt")

+                             try:

+                                 with open("fesco_issue.txt", "r") as pg_txt:

+                                     issue_text = pg_txt.read()

+                                 if system_wide_change == True:

+                                     syschange = "System-Wide Change"

+                                 elif system_wide_change == False:

+                                     syschange = "Self-Contained Change"

+                                 title = "F" + str(fedora_version) + ' ' + str(syschange) + ':' + str(subject) 

+                                 #print(issue_text)

+                                 payload = {

+                                             'title': title,

+                                             'issue_content': issue_text

+                                 }

+                                 #print(title, payload)

+                                 repo = config['PAGURE']['FESCO_REPO']          

+                                 r = pgaissues.post_issue(payload, repo, config)

+                                 #print(r)

+                                 if r.status_code == 200:

+                                     payload = {

+                                                 'status': config['TAIGA']['ISSUE_STATUS_READY_FOR_FESCO'],

+                                                 'version': taiga_issue_version

+                                     }

+                                     r = tgaissue.changestatus_issue(taiga_issue_id, payload, config)

+                                     print("Succesfully posted issue")

+                                 else:

+                                     print("Check logs for errors",json.loads(r.content))

+                             except requests.exceptions.RequestException as e:

+                                 print(e)

+                                 log_exception(e)

+                         except Exception as e:

+                             print(e)

+                             log_exception(e)

+                     else:

+                         print("Unable to post to fesco")

+                 except requests.exceptions.RequestException as e:

+                     print(e)

+                     log_exception(e)

+             else:

+                 print("Unable to fetch details from taiga for issue creation")

+         except requests.exceptions.RequestException as e:

+             print(e)

+             log_exception(e)

file added
+91
@@ -0,0 +1,91 @@ 

+ import requests

+ import configparser

+ import keyring

+ import json

+ 

+ """

+ headers = {

+             'Content-Type': 'application/x-www-form-urlencoded',

+             'Authorization': token {}.format(keyring.get_password(service_token, "repo_name"))

+ }

+ """

+ 

+ 

+ def list_issue(config):

+     """kusts ussyes"""

+     try:

+         """

+         repo_name = (config['PAGURE']['SERVICE_ID'], "repo_name")

+         print(repo_name)

+         """

+         headers = {

+                 'Content-Type': 'application/json',

+                 'Authorization': 'token {0}'.format(keyring.get_password(config['PAGURE']['SERVICE_ID'], "repo_name"))

+         }

+         url = str(config['PAGURE']['URL']) + '/issues'

+     

+         r = requests.get(

+             url,

+             headers=headers,

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def get_issue(issueid, config):

+     """gets issue from pagure"""

+     try:

+         """

+         repo_name = (config['PAGURE']['SERVICE_ID'], "repo_name")

+         print(repo_name)

+         """

+         headers = {

+                 'Content-Type': 'application/json',

+                 'Authorization': 'token {0}'.format(keyring.get_password(config['PAGURE']['SERVICE_ID'], "repo_name"))

+         }

+         url = str(config['PAGURE']['URL']) + "/issue/" + str(issueid)

+     

+         r = requests.get(

+             url,

+             headers=headers,

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def post_issue(payload, repo, config):

+     """ Posts issue to pagure """

+     try:

+         #repo_name = (config['PAGURE']['SERVICE_ID'], "repo_name")

+         #print(repo_name)

+         headers = {

+                 'Content-Type': 'application/json',

+                 'Authorization': 'token {0}'.format(keyring.get_password(config['PAGURE']['SERVICE_ID'], repo))

+         }

+         #print(headers)

+         url = str(config['PAGURE']['API_URL']) + repo + '/new_issue'

+         #print(data) # debug only

+         #print(url)

+         #print(payload)

+         r = requests.post(

+             url,

+             data=json.dumps(payload),

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e) 

\ No newline at end of file

file added
+34
@@ -0,0 +1,34 @@ 

+ import requests

+ import json

+ import keyring

+ import random

+ import os

+ import binascii

+ import getpass

+ import configparser

+ 

+ from logger import setup_logging_to_file, log_exception

+ 

+ def reset(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     print("Your auth token will be securly store in the Keyring")

+     # username = input("Enter your user id for taiga: ")

+     service_id = config['PAGURE']['SERVICE_ID']

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     #repo_name = input("Enter the repo name you want to set api key for: ")

+     fescotoken = getpass.getpass("Enter your token for" + ' ' + "fesco" + ' ' "repository: ")

+     releasetoken = getpass.getpass("Enter your token for" + ' ' + "release-notes" + ' ' "repository: ")

+     try:

+         # keyring.set_password("taiga", username)

+         #keyring.set_password(service_id, "repo_name", repo_name)

+         keyring.set_password(service_id, config['PAGURE']['FESCO_REPO'], str(fescotoken))

+         keyring.set_password(service_id, config['PAGURE']['RELEASE_NOTES_REPO'], str(releasetoken))

+         print("token reset succesfully")

+     except (keyring.errors.PasswordSetError, Exception) as e:

+         print("Failed to reset token")

+         print(e)

+         log_exception(e)

+         # print(e + "Contact the developers asap")

file added
+71
@@ -0,0 +1,71 @@ 

+ apturl==0.5.2

+ asn1crypto==0.24.0

+ Brlapi==0.6.6

+ bugzilla==1.0.0

+ certifi==2019.3.9

+ cffi==1.12.3

+ chardet==3.0.4

+ command-not-found==0.3

+ cryptography==2.6.1

+ cupshelpers==1.0

+ dbus-python==1.2.8

+ defer==1.0.6

+ distro-info===0.18ubuntu0.18.04.1

+ entrypoints==0.3

+ flake8==3.7.7

+ httplib2==0.9.2

+ idna==2.8

+ jeepney==0.4

+ keyring==19.0.2

+ keyrings.alt==3.0

+ language-selector==0.1

+ launchpadlib==1.10.6

+ lazr.restfulclient==0.13.5

+ lazr.uri==1.0.3

+ louis==3.5.0

+ macaroonbakery==1.1.3

+ Mako==1.0.7

+ MarkupSafe==1.0

+ mccabe==0.6.1

+ netifaces==0.10.4

+ oauth==1.0.1

+ olefile==0.45.1

+ pexpect==4.2.1

+ Pillow==5.1.0

+ protobuf==3.0.0

+ psutil==5.6.1

+ pycairo==1.16.2

+ pycodestyle==2.5.0

+ pycparser==2.19

+ pycrypto==2.6.1

+ pycups==1.9.73

+ pyflakes==2.1.1

+ pygobject==3.26.1

+ pymacaroons==0.13.0

+ PyNaCl==1.1.2

+ pyRFC3339==1.0

+ python-apt==1.6.4

+ python-dateutil==2.6.1

+ python-debian==0.1.32

+ python-editor==1.0.4

+ pytz==2018.3

+ pyxdg==0.25

+ PyYAML==3.12

+ reportlab==3.4.0

+ requests==2.22.0

+ requests-unixsocket==0.1.5

+ screen-resolution-extra==0.0.0

+ SecretStorage==3.1.1

+ simplejson==3.13.2

+ six==1.12.0

+ system-service==0.3

+ systemd-python==234

+ ubuntu-drivers-common==0.0.0

+ ufw==0.36

+ unattended-upgrades==0.1

+ urllib3==1.25.2

+ usb-creator==0.3.3

+ virtualenv==15.1.0

+ wadllib==1.3.2

+ xkit==0.0.0

+ zope.interface==4.3.2

file added
+245
@@ -0,0 +1,245 @@ 

+ import os

+ import requests

+ import json

+ import keyring

+ import configparser

+ from tga import epics as tgaepic

+ from tga import issues as tgaissue

+ from tga import userstory as tgauserstory

+ from logger import setup_logging_to_file, log_exception

+ 

+ """

+ config = configparser.ConfigParser()

+ config.read('config.ini')

+ #config.read('%s' % (configpath))

+ #config.read(['userconfig.ini', os.path.expanduser('~/.')])

+ 

+ service_id = config['TAIGA']['SERVICE_ID']  # service id

+ service_token = config['TAIGA']['SERVICE_TOKEN']

+ project_id = config['TAIGA']['PROJECT_ID']

+ taiga_url = config['TAIGA']['CUSTOM_TAIGA_URL']

+ """

+ """

+ if config['TAIGA']['TEST'] == 'yes':

+     taiga_url = config['TAIGA']['CUSTOM_TAIGA_URL']

+ elif config['TAIGA']['TEST'] == 'no':

+     taiga_url = config['TAIGA']['DEFAULT_TAIGA_URL']

+ else:

+     print("please set test status in config")

+ """

+ 

+ 

+ def convert(value, configpath):

+     #configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['TAIGA']['SERVICE_ID']  # service id

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     taiga_url = config['TAIGA']['TAIGA_URL']

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     #value = args.taiga

+     for x in value:

+         try:

+             #print(x,"this is x")

+             issueurl, r = tgaissue.get_issue(x, config)  # gets the issue

+             if r.status_code == 200 :

+                 data = json.loads(r.content)

+                 print(data, "this is issue data")

+                 details = data['description']

+                 subject = data['subject']

+                 issue_id = data['id']

+                 issue_ref = data['ref']

+                 issue_version = data['version']

+                 #print(issue_version, "this is issue version")

+                 #print("this is issue version")  # fetch the id as well

+                 #print(issue_id)

+                 #print("Step 1")

+                 """

+                 try:

+                     Because issue id is required to get custom attributes

+                     issues cannot be fetched via refrance id so fetching

+                     the issue by refrence first and then using the id

+                     returned in json to fetch the custom-attributes via

+                     issue id.

+                     Since only refrence is taken via command line

+                     and issue id is difficult to find in taiga                  

+                     # print(headers)  # Debug only

+                     # id_url = str(taiga_url) + "/api/v1/issues/custom-attributes-values" + "/{" + id + "}"

+                     # print(id_url)  # debug only               

+                     issue_customattr = requests.get(

+                         id_url,

+                         headers=headers,

+                     )

+                 """

+                 try:

+                     r = tgaissue.caget_issue(issue_id, config)

+                     if r.status_code == 200:

+                         data = json.loads(r.content)

+                         if data['status'] == config['TAIGA']['ISSUE_STATUS_PROCESSED']

+                             print("Already processed")

+                         else:

+                             #print(r.content)

+                             #print(data, "step 2")

+                             #system_wide_change = data['attributes_values']['1']

+                             # rel-eng-ticket = data['attributes_values']['7'] # bug in taiga thus the later no

+                             summary = data['attributes_values'][config['TAIGA']['ISSUE_CA_SUMMARY']] # ['11372']

+                             bugzilla_id = data['attributes_values'][config['TAIGA']['ISSUE_CA_BUGZILLA_CONTACT']] # ['11373']

+                             approval_required = data['attributes_values'][config['TAIGA']['ISSUE_CA_TRADEMARK_APPROVAL']] #['11374']

+                             owners = data['attributes_values'][config['TAIGA']['ISSUE_CA_OWNERS']]#['11375']

+                             contingency_deadline = data['attributes_values'][config['TAIGA']['ISSUE_CA_CONTINGENCY']]#['11376']

+                             mass_rebuild = data['attributes_values'][config['TAIGA']['ISSUE_CA_MASS_REBUILD']]#['11377']

+                             policy_change = data['attributes_values'][config['TAIGA']['ISSUE_CA_POLICY_CHANGE']]#['11378']

+                             modifies_deliverables = data['attributes_values'][config['TAIGA']['ISSUE_CA_MODIFIES_DELIVERABLES']]#['11379']

+                             system_wide_change = data['attributes_values'][config['TAIGA']['ISSUE_CA_SYSTEM_WIDE_CHANGE']]#['11370']

+                             relengticket = data['attributes_values'][config['TAIGA']['ISSUE_CA_RELENG_TICKET']]#['11371']

+                             fedora_version = data['attributes_values'][config['TAIGA']['ISSUE_CA_VERSION']]#['11383']

+                             #print(fedora_version)

+                             #print("summary", summary)

+                             #print(bugzilla_id)

+                             #print("Fetched Custom Attributes")

+                             """

+                             Taiga api returns no's instead of the actual names/description

+                             The below no's stand for changes tracker fesco,change-wrangler

+                             1 = System-wide change

+                             2 = Summary

+                             3 = Bugzilla id

+                             4 = Missing

+                             5 = Trademark approval required

+                             6 = Owners

+                             7 = Rel-eng ticket/Rel-end impact ticket

+                             11 = Contingencry deadline

+                             12 = Mass rebuild required

+                             13 = Policy change required

+                             14 = Modifies deliverables

+                             """

+                             try:

+                                 payload = {

+                                             'project': project_id,

+                                             'description': details,

+                                             'subject': subject

+                                 }

+                                 #print(payload)

+                                 r = tgauserstory.post_us(payload, config)

+                                 #print(json.loads(r.content))

+                                 data = json.loads(r.content)

+                                 #print(r.status_code)

+                                 if r.status_code == 201:

+                                     #print("step 3")

+                                     data = json.loads(r.content)

+                                     userstoryid = data['id']

+                                     userstoryref = data['ref']

+                                     userstory_version = data['version']

+                                     #print(id)

+                                     issueurl = str(config['TAIGA']['PROJECT_WEB_URL']) + str(config['TAIGA']['PROJECT_WEB_NAME']) +'/issue/'+ str(issue_ref)

+                                     payload = {

+                                                 "attributes_values": {

+                                                     config['TAIGA']['USERSTORY_CA_SYSTEM_WIDE_CHANGE']: system_wide_change,

+                                                     config['TAIGA']['USERSTORY_CA_SUMMARY']: summary,

+                                                     config['TAIGA']['USERSTORY_CA_RELENG_TICKET']: relengticket,

+                                                     config['TAIGA']['USERSTORY_CA_TRADEMARK_APPROVAL']: approval_required,

+                                                     #config['TAIGA']['USERSTORY_CA_OWNERS']: owners,

+                                                     config['TAIGA']['USERSTORY_CA_FESCO_TICKET']: 'random',

+                                                     config['TAIGA']['USERSTORY_CA_BUGZILLA_TRACKER']: 'random',

+                                                     config['TAIGA']['USERSTORY_CA_BUGZILLA_CONTACT']: bugzilla_id,

+                                                     config['TAIGA']['USERSTORY_CA_RELEASE_NOTES']: 'random',

+                                                     config['TAIGA']['USERSTORY_CA_CONTINGENCY']: contingency_deadline,

+                                                     config['TAIGA']['USERSTORY_CA_MASS_REBUILD']: mass_rebuild,

+                                                     config['TAIGA']['USERSTORY_CA_POLICY_CHANGE']: policy_change,

+                                                     config['TAIGA']['USERSTORY_CA_MODIFIES_DELIVERABLES']: modifies_deliverables,

+                                                     config['TAIGA']['USERSTORY_CA_ISSUE_LINK']: issueurl

+                                                 },

+                                                 "version": userstory_version

+                                     }

+                                     #print(payload)

+                                     r = tgauserstory.post_usca(payload, userstoryid, config)

+                                     #print(json.loads(r.content))

+                                     #print(r.status_code)

+                                     if r.status_code == 200:

+                                         print("Sucessfully mapped issue custom attirbutes to userstory")

+                                         try:

+                                             r = tgaepic.list_epic(config)

+                                             data = json.loads(r.content)

+                                             if r.status_code == 200:

+                                                 for i in data:

+                                                     if i['subject'] == str(fedora_version):

+                                                         epicid = i['id']

+                                                         epicref = i['ref']

+                                                         break

+                             

+                                             r = tgaepic.post_relatedus(userstoryid, epicid, epicref, config)

+                                             #print(r.content, r.status_code)

+                                             if r.status_code == 201:

+                                                 data = json.loads(r.content)

+                                                 print("Sucessfully mapped epics")

+                                                 payload = {

+                                                             'status': config['TAIGA']['USERSTORY_STATUS_ACCEPTED'],

+                                                             'version': userstory_version

+                                                 }

+                                                 r = tgauserstory.changestatus_userstory(userstoryid, payload, config)

+                                                 #print(r.content,r.status_code)

+                                                 if r.status_code == 200:

+                                                     userstoryurl = str(config['TAIGA']['PROJECT_WEB_URL']) + str(config['TAIGA']['PROJECT_WEB_NAME']) +'/us/'+ str(userstoryref)

+                                                     issue_version = issue_version # + 1 

+                                                     #print(type(issue_version))

+                                                     #print(issue_version)

+                                                     payload = {

+                                                                 'version': issue_version,

+                                                                 "comment": userstoryurl 

+                                                     }       

+                                                     r = tgaissue.edit_issue(payload, issue_id, config)

+                                                     if r.status_code == 200: 

+                                                         data = json.loads(r.content)

+                                                         issue_version = data['version']

+                                                         print("Sucessfully converted issue to user story")  

+                                                         issue_version = issue_version #+1 

+                                                         payload = {

+                                                                     'status': config['TAIGA']['ISSUE_STATUS_PROCESSED'],

+                                                                     'version': issue_version

+                                                         }

+                                                         r = tgaissue.changestatus_issue(issue_id, payload, config)

+                                                         #print(r.status_code)

+                                                         #print(r.content)

+                                                         if r.status_code == 200:

+                                                             print("Sucessfully closed issue")

+                                                             return userstoryid, True

+                                                         else:

+                                                             print("Unsuccesful at closing issue,check logs")

+                                                     else:

+                                                         print("Unable to map Issue url to user story attributes")

+                                                 else:

+                                                     print("Converted User story,copied attributes mapped epics,faliure to change status to accepted")

+                                             else:

+                                                 print("Unnsucessful to map to epics,change user story status to accepted and issue status to processed")

+                                         except requests.exceptions.RequestException as e:

+                                             print(e)

+                                             log_exception(e)

+                                         except Exception as e:

+                                             print(e)

+                                             log_exception(e)

+                                     else:

+                                         print("Unsuccesful Conversion")

+                                 else:

+                                     print("Unsuccesful conversion")

+                         except requests.exceptions.RequestException as e:

+                             print(e)

+                             log_exception(e)

+                         except Exception as e:

+                             print(e) 

+                             log_exception(e)   

+                     else:

+                         print("Unsuccesful Conversion")         

+                 except requests.exceptions.RequestException as e:

+                     print("Failed to fetch attributes of the issue")

+                     print(e)

+                     log_exception(e)

+             else:

+                 print("Unable to Convert Issue,Check logs and contact the developer", json.loads(r.content))

+         except Exception as e:

+             print(e)

+             log_exception(e)

+         except requests.exceptions.RequestException as e:

+             print(e)

+             log_exception(e)

+ 

file added
+143
@@ -0,0 +1,143 @@ 

+ import os

+ import requests

+ import json

+ import keyring

+ import configparser

+ import logger

+ import editor

+ import sys

+ 

+ from tga import epics as tgaepic

+ from tga import issues as tgaissue

+ from tga import userstory as tgauserstory

+ from logger import setup_logging_to_file, log_exception

+ 

+ def create(args):

+     configpath = args.config 

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['TAIGA']['SERVICE_ID']  # service id

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     taiga_url = config['TAIGA']['TAIGA_URL']

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     title = input("Enter the title of the issue: ")

+     description = input("Enter the Description of the issue: ")

+     change_type = input("System Wide Change ? Yes/No : ")

+     link_releng = input("Enter the link to releng ticket : ")

+     summary = input("Summary of the issue: ")

+     bugzilla = input("Bugzilla Email adress: ")

+     approval = input("Does this change proposal require approval ? Yes or No ? : ")

+     owners = input("Enter the FAS ID of the Owner: ")

+     deadline = input(" Enter Contingency Deadline , 1-BranchPoint, 2-BetaFreeze, 3-Final Freeze: ")

+     massrebuild = input("Is Mass rebuild required ? Yes or No ? : ")

+     policy_change = input("Is policy_change required ?  Yes/No : ")

+     modified_deliverables = input("Does this create or remove something ? Yes/No : ")

+     fedora_version = input("Input the Fedora-Version: ")

+     change_subtype = input("Input The Change Type 1-Bug, 2-Question, 3- Enhancement: ")

+     servity = input("Input the servity of the issue 1-Normal, 2-Wishlist, 3-Minor, 4-Important, 5-Critical :  ")

+     priority = input("Input the priority type 1-Normal, 2-Low, 3-High : ")

+     with open("post_isssue.txt", "w+") as pissue_txt:

+         pissue_txt.write("Description: {} \n ".format(description))

+     editor.edit(filename="post_isssue.txt")

+     try:

+         if change_subtype == str(1):

+             change_subtype = config['TAIGA']['ISSUE_TYPE_BUG']

+         elif change_subtype == str(2):

+             change_subtype = config['TAIGA']['ISSUE_TYPE_QUESTION']

+         elif change_subtype == str(3):

+             change_subtype = config['TAIGA']['ISSUE_TYPE_ENHANCEMENT']

+         else:

+             print("error in change type input")

+ 

+         if servity == str(1):

+             servity = confg['TAIGA']['ISSUE_SERVITY_NORMAL']

+         elif servity == str(2):

+             servity = config['TAIGA']['ISSUE_SERVITY_WISHLIST']

+         elif servity == str(3):

+             servity = config['TAIGA']['ISSUE_SERVITY_MINOR']

+         elif servity == str(4):

+             servity = config['TAIGA']['ISSUE_SERVITY_IMPORTANT']

+         elif servity == str(5):

+             servity = config['TAIGA']['ISSUE_SERVITY_CRITICAL']

+         else:

+             print("error in issue servity input")

+ 

+         if priority == str(1):

+             priority = config['TAIGA']['ISSUE_PRIORITIES_NORMAL']

+         elif priority == str(2):

+             priority = config['TAIGA']['ISSUE_PRIORITIES_LOW']

+         elif priority == str(3):

+             priority = config['TAIGA']['ISSUE_PRIORITIES_HIGH']

+         else:

+             print("Error in priority input")

+ 

+         if change_type == "Yes":

+             change_type = True 

+         elif change_type == "No":

+             change_type = False

+ 

+         if approval == "Yes":

+             approval == True 

+         elif approval == "No":

+             approval == False

+ 

+         if massrebuild == "Yes":

+             massrebuild == True

+         elif massrebuild == "No":

+             massrebuild == False

+ 

+         if policy_change == "Yes":

+             policy_change == True

+         elif policy_change == "No":

+             policy_change == False

+ 

+         if modified_deliverables == "Yes":

+             modified_deliverables == True

+         elif modified_deliverables == "No":

+             modified_deliverables == False

+ 

+         with open("post_isssue.txt", "r") as pissue_txt:

+             description = pissue_txt.read()

+         payload = {

+                     "subject": title,

+                     "description": description,

+                     "project": config['TAIGA']['PROJECT_ID'],

+                     "servity": servity,

+                     "priority": priority,

+                     "status": config['TAIGA']['ISSUE_STATUS_NEW'],

+                     "type": change_subtype

+         }

+         r = tgaissue.post_issue(payload, config)

+         if r.status_code == 200:

+             issuedata = josn.loads(r.content)

+             ref = issuedata['ref']

+             id = issuedata['id']

+             payload = {

+                         "attributes_values": {

+                             config['TAIGA']['ISSUE_CA_SYSTEM_WIDE_CHANGE']: change_type,

+                             config['TAIGA']['ISSUE_CA_SYSTEM_SUMMARY']: summary,

+                             config['TAIGA']['ISSUE_CA_SYSTEM_BUGZILLA_CONTACT']: bugzilla,

+                             config['TAIGA']['ISSUE_CA_TRADEMARK_APPROVAL']: approval, 

+                             config['TAIGA']['ISSUE_CA_OWNERS']: owners,    

+                             config['TAIGA']['ISSUE_CA_MASS_REBUILD']: massrebuild, 

+                             config['TAIGA']['ISSUE_CA_POLICY_CHANGE']: policy_change, 

+                             config['TAIGA']['ISSUE_CA_MODIFIES_DELIVERABLES']: modified_deliverables,

+                             config['TAIGA']['ISSUE_CA_RELENG_TICKET']: link_releng

+                         }

+             }

+             r = tgaissue.capatch_issue(id, payload, config)

+             if r.status_code == 200:

+                 print("Succesfully Created Issue")

+             else:

+                 print("Unable to create issue check log for errors")

+         else:

+             print("Unable to create issue check log for errors")

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

file added
+105
@@ -0,0 +1,105 @@ 

+ import json

+ import configparser

+ import keyring

+ import requests

+ 

+ """

+ config = configparser.ConfigParser()

+ config.read('config.ini')

+ """

+ """

+ service_id = config['TAIGA']['SERVICE_ID']  # service id

+ service_token = config['TAIGA']['SERVICE_TOKEN']

+ project_id = config['TAIGA']['PROJECT_ID']

+ 

+ if config['TAIGA']['TEST'] == 'yes':

+     taiga_url = config['TAIGA']['CUSTOM_TAIGA_URL']

+     status = config['TAIGA']['TEST_US_STATUS_R_FESCO']

+ elif config['TAIGA']['TEST'] == 'no':

+     taiga_url = config['TAIGA']['DEFAULT_TAIGA_URL']

+     status = config['TAIGA']['STATUS']

+ else:

+     print("please set test status in config")

+ """

+ """

+ headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+ }

+ """

+ 

+ 

+ def list_epic(config):

+     try:

+         """

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         """

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+         }

+         url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/epics?project=" + str(config['TAIGA']['PROJECT_ID'])

+         #print(url)

+         r = requests.get(

+             url,

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def post_relatedus(USERSTORY_id, epicid, epicref, config):

+     try:

+         """

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         """

+         url = str(config['TAIGA']['TAIGA_URL']) + '/api/v1/epics/' + str(epicid) + '/related_userstories',

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+         }

+         payload = {

+             "epic": epicid,

+             "user_story": USERSTORY_id

+         }

+         r = requests.post(

+             'https://api.taiga.io/api/v1/epics/' + str(epicid) + '/related_userstories',

+             data=json.dumps(payload),

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ def listrelepic_userstory(epicid, config):

+     #url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/userstories?project=" + str(config['TAIGA']['PROJECT_ID']) + "&epic=" + epicid

+     url = str(config['TAIGA']['TAIGA_URL']) + '/api/v1/epics/' + str(epicid) + '/related_userstories'

+     print(url)

+     headers = {

+         'Content-Type': 'application/json',

+         'x-disable-pagination': 'True',

+         'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+     }

+     try:

+         r = requests.get(

+             url,

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e) 

\ No newline at end of file

file added
+239
@@ -0,0 +1,239 @@ 

+ import json

+ import configparser

+ import keyring

+ import requests

+ 

+ from prettytable import PrettyTable

+ from logger import setup_logging_to_file, log_exception

+ """

+ config = configparser.ConfigParser()

+ config.read('config.ini')

+ 

+ service_id = config['TAIGA']['SERVICE_ID']  # service id

+ service_token = config['TAIGA']['SERVICE_TOKEN']

+ project_id = config['TAIGA']['PROJECT_ID']

+ 

+ if config['TAIGA']['TEST'] == 'yes':

+     taiga_url = config['TAIGA']['CUSTOM_TAIGA_URL']

+     status = config['TAIGA']['TEST_ISSUE_STATUS_NEW']

+ elif config['TAIGA']['TEST'] == 'no':

+     taiga_url = config['TAIGA']['DEFAULT_TAIGA_URL']

+     status = config['TAIGA']['ISSUE_STATUS_NEW']

+ else:

+     print("please set test status in config")

+ 

+ 

+ headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(service_token, "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+ }

+ """

+ 

+ 

+ def list_issue(args):

+     try:

+         configpath = args.config

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/issues?project=" + config['TAIGA']['PROJECT_ID'] + "&status=" + str(config['TAIGA']['ISSUE_STATUS_NEW'])

+         #print(url)  # Debug only

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         try:

+             r = requests.get(

+                 url,

+                 headers=headers

+             )

+             if r.status_code == 200:

+                 table = PrettyTable()

+                 table.field_names = ["refrence no", "subject", "fedora-version"]

+                 data = json.loads(r.content)

+                 for item in data:

+                     #print(item)

+                     due_date = item['due_date']

+                     issueid = item['id']

+                     issueref= item['ref']

+                     subject = item['subject']

+                     version = item['version']

+                     #print(issueref)

+                     r = caget_issue(issueid, config)

+                     if r.status_code == 200:

+                         cadata = json.loads(r.content)

+                         version = cadata['attributes_values'][config['TAIGA']['ISSUE_CA_VERSION']] #['11383']

+                     else:

+                         print("Error fetching Fedora Version,check logs for errors")

+                     """

+                     for item in data['owner_extra_info']:

+                         print(item)

+                         owner = item['username']

+                     """

+                     table.add_row([issueref, subject, version])

+                 print(table)

+             else:

+                 print("Unable to fetch list check logs")

+                 #print(r.content)

+         except requests.exceptions.RequestException as e:

+             print(e)

+             log_exception(e)

+         except Exception as e:

+             print(e)

+             log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def get_issue(x, config):

+     

+     try:

+         """

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         """

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/issues/by_ref?ref=" + str(x) + "&project=" + str(config['TAIGA']['PROJECT_ID'])

+         #print(headers)

+         #print(url)  # debug/dev env only

+         r = requests.get(

+             url,

+             headers=headers

+         )

+         return url, r 

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ def caget_issue(x, config):

+     """

+     Gets custom attributes from taiga for issue

+     

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     """

+     headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+     }

+     #print(x)

+     id_url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/issues/custom-attributes-values/" + str(x)   # x is issue id

+     #print(id_url)

+     try:

+         r = requests.get(

+             id_url,

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ def capatch_issue(x, payload, config):

+     try:

+         headers = {

+                 'Content-Type': 'application/json',

+                 'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+                 # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         #print(x)

+         id_url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/issues/custom-attributes-values/" + str(x)

+         r = request.patch(

+             id_url,

+             headers=headers,

+             data=json.dumps(payload)

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def changestatus_issue(x, payload, config):

+     """

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     """

+     id_url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/issues/" + str(x)  # x is id

+     headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+     }

+     """

+     payload = {

+                 'status': config['TAIGA']['ISSUE_STATUS_PROCESSED'],

+                 'version': issue_version

+     }

+     """

+     try:

+         r = requests.patch(

+             id_url,

+             data=json.dumps(payload),

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ def edit_issue(x, id, config):

+     #url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/issues?project=" + config['TAIGA']['PROJECT_ID'] + "&status=" + str(config['TAIGA']['ISSUE_STATUS_NEW'])

+     try:

+         url = str(config['TAIGA']['TAIGA_URL']) + "api/v1/issues/" + str(id)

+         headers = {

+                 'Content-Type': 'application/json',

+                 'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+                 # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         r = requests.patch(

+             url,

+             #'https://api.taiga.io/api/v1/userstories/custom-attributes-values/' + str(id),

+             data=json.dumps(x),

+             headers=headers

+         )

+         #print(json.loads(r.content))

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ def post_issue(x, config):

+     try:

+         url = str(config['TAIGA']['TAIGA_URL']) +  "api/v1/issues/" 

+         headers = {

+                 'Content-Type': 'application/json',

+                 'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+         }

+         r = request.post(

+             url,

+             data=json.dumps(x),

+             headers=headers

+         )

+         #print(json.loads(r.content))

+         return r

+     except Exception as e:

+         print(e)

+         log_exception(e) 

\ No newline at end of file

file added
+122
@@ -0,0 +1,122 @@ 

+ import requests

+ import json

+ import keyring

+ import random

+ import os

+ import binascii

+ import getpass

+ import configparser

+ import keyring

+ 

+ """

+ config = configparser.ConfigParser()

+ config.read(config(filename))

+ 

+ service_id = config['TAIGA']['SERVICE_ID']  # service id

+ service_token = config['TAIGA']['SERVICE_TOKEN']  # service d for auth

+ # taiga_url = config['TAIGA']['DEFAULT_TAIGA_URL']  # taiga server note

+ # custom_taiga = config['TAIGA']['CUSTOM_TAIGA_URL']

+ project_id = config['TAIGA']['PROJECT_ID']

+ taiga_url = config['TAIGA']['TAIGA_URL']

+ """

+ """

+ if config['TAIGA']['TEST'] == 'yes':

+     taiga_url = config['TAIGA']['CUSTOM_TAIGA_URL']

+ elif config['TAIGA']['TEST'] == 'no':

+     taiga_url = config['TAIGA']['DEFAULT_TAIGA_URL']

+ else:

+     print("please set test status in config")

+ """

+ 

+ 

+ def refresh_token(args):

+     """

+     Used only for testing and Demo

+     Encrypted Config file/Application token

+     used in production.

+     Doing the follwoing in prod is security risk.

+     """

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     headers = {

+             'Content-Type': 'application/json',

+     }

+     service_id = config['TAIGA']['SERVICE_ID']

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     taiga_url = config['TAIGA']['TAIGA_URL']

+     username = keyring.get_password(service_id, "taiga_username")

+     #print(username) # debug only

+     payload = {

+                 'type': 'normal',

+                 'username': username,

+                 'password': keyring.get_password(service_id, username)

+     }

+     #print(payload) # only for debugging

+ 

+     try:

+         r = requests.post(

+             str(taiga_url) + "/api/v1/auth",

+             data=json.dumps(payload),

+             headers=headers)

+         #print(r.status_code)

+         if r.status_code == 200:

+             """

+             with open('auth.txt', 'w') as a_file:

+                 a_file.write(r.json()['auth_token'])

+             """

+             try:

+                 keyring.set_password(service_token, "taiga_token", r.json()['auth_token'])

+                 print("succesful authentication")

+             except (keyring.errors.PasswordSetError, Exception) as e:

+                 print("Failed to set auth token,check log for errors")

+                 #print(e)

+                 log_exception(e)

+         elif r.status_code == 400:

+             print("auth error")

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def reset(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     headers = {

+             'Content-Type': 'application/json',

+     }

+     service_id = config['TAIGA']['SERVICE_ID']

+     print("You User Id and password will be securly store in the Keyring")

+     username = input("Enter your user id for taiga: ")

+     password = getpass.getpass("Enter your password for taiga: ")

+     try:

+         """

+         So a workaround to store username along with pass is being used

+         the only drawback ofthis work around is in the gui keyring broswer

+         a seperate username keyring will show,sadly this cannot be avoided

+         at the point of writing this peice of software

+         """

+         """

+         The above comment is not true 

+         """

+         keyring.set_password(service_id, "taiga_username", username) # refer line 67

+         keyring.set_password(service_id, username, str(password))

+         username = binascii.hexlify(os.urandom(20))  # randomising username to avoid sneak memory attacks

+         password = binascii.hexlify(os.urandom(20))  # ranomising pass to avoid sneak memory attacks

+         print("Password reset succesfully")

+     except (keyring.errors.PasswordSetError, Exception) as e:

+         print("Failed to reset password check log for errors")

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

file added
+247
@@ -0,0 +1,247 @@ 

+ import configparser

+ import json

+ import keyring

+ import requests

+ 

+ from prettytable import PrettyTable

+ 

+ config = configparser.ConfigParser()

+ config.read('config.ini')

+ 

+ """

+ service_id = config['TAIGA']['SERVICE_ID']  # service id

+ service_token = config['TAIGA']['SERVICE_TOKEN']

+ project_id = config['TAIGA']['PROJECT_ID']

+ 

+ if config['TAIGA']['TEST'] == 'yes':

+     taiga_url = config['TAIGA']['CUSTOM_TAIGA_URL']

+     status = config['TAIGA']['TEST_USERSTORY_STATUS_NEW']

+ elif config['TAIGA']['TEST'] == 'no':

+     taiga_url = config['TAIGA']['DEFAULT_TAIGA_URL']

+     status = config['TAIGA']['USERSTORY_STATUS_NEW']

+ else:

+     print("please set test status in config")

+ 

+ headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(service_token, "taiga_token"))

+ }

+ """

+ 

+ 

+ def list_us(args):

+     try:

+         configpath = args.config

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         #print(headers)

+         url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/userstories?project=" + str(config['TAIGA']['PROJECT_ID']) + "&status=" + str(config['TAIGA']['USERSTORY_STATUS_NEW'])

+         #url = "https://api.taiga.io/api/v1/issues?project=325667\&status=2283176"

+         #print(url)  # Debug only

+         try:

+             r = requests.get(

+                 url,

+                 headers=headers

+             )

+             if r.status_code == 200:

+                 #print(r.status_code)

+                 table = PrettyTable()

+                 table.field_names = ["refrence no", "subject", "fedora-version"]

+                 data = json.loads(r.content)

+                 for item in data:

+                     subject = item['subject']

+                     USERSTORY_id = item['id']

+                     USERSTORY_ref = item['ref']

+                     version = item['epics']

+                     duedate = item['due_date']

+                     tags = ['tags']

+                     r = caget_us(USERSTORY_id, config)

+                     if r.status_code == 200:

+                         cadata = json.loads(r.content)

+                         version = cadata['attributes_values'][config['TAIGA']['US']]

+                     """

+                     for item in data['owner_extra_info']:

+                         owner = item['username']

+                     """

+                     table.add_row([USERSTORY_ref, subject, version])

+                     #print(USERSTORY_id, USERSTORY_ref owner)

+                 #print(table)

+             else:

+                 print("check logs for error,unable to process")

+         except requests.exceptions.RequestException as e:

+             print(e)

+             #print(r.content)

+             log_exception(e)

+         except Exception as e:

+             print(e)

+             log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def get_us(usid, config):

+     try:

+         """

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         """

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         #url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/userstories/by_ref?ref=" + str(refusid) + "\&project=" + str(config['TAIGA']['PROJECT_ID'])

+         #url = "https://api.taiga.io/api/v1/issues?project=325667\&status=2283176"

+         url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/userstories/" + str(usid)

+         #print(url) # debug only

+         r = requests.get(

+             url,

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def caget_us(usid, config):

+     try:

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+         }

+         url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/userstories/" + "/custom-attributes-values/" + str(usid)

+         r = requests.get(

+             url,

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def post_us(x, config):

+     try:

+         """

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         """

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         r = requests.post(

+             'https://api.taiga.io/api/v1/userstories',

+             data=json.dumps(x),

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def post_usca(x, id, config):

+     try:

+         """

+         config = configparser.ConfigParser()

+         config.read(configpath)

+         

+         if url == True:

+             

+         else:

+             url = url 

+         """

+         url = 'https://api.taiga.io/api/v1/userstories/custom-attributes-values/' + str(id)

+         headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+         }

+         r = requests.patch(

+             url,

+             #'https://api.taiga.io/api/v1/userstories/custom-attributes-values/' + str(id),

+             data=json.dumps(x),

+             headers=headers

+         )

+         #print(json.loads(r.content))

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def changestatus_userstory(x, payload, config):

+     """

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     """

+     id_url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/userstories/" + str(x)  # x is id

+     print(id_url)

+     headers = {

+             'Content-Type': 'application/json',

+             'Authorization': 'Bearer {0}'.format(keyring.get_password(config['TAIGA']['SERVICE_TOKEN'], "taiga_token"))

+             # 'Authorization': 'Bearer {0}'.format(str(123))

+     }

+     """

+     payload = {

+                 'status': config['TAIGA']['ISSUE_STATUS_PROCESSED'],

+                 'version': issue_version

+     }

+     """

+     try:

+         r = requests.patch(

+             id_url,

+             data=json.dumps(payload),

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ 

+ def listrelepic_userstory(epicid, config):

+     url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/userstories?project=" + str(config['TAIGA']['PROJECT_ID']) + "&epic=" + epicid

+     try:

+         r = requests.get(

+             url,

+             headers=headers

+         )

+         return r

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ """

+ curl -X GET \

+ -H "Content-Type: application/json" \

+ -H "Authorization: Bearer ${eyJ1c2VyX2F1dGhlbnRpY2F0aW9uX2lkIjozNTY4MDR9:1hI6pm:4d4mA-gUXC2S0FxaladX0Fd_3gA}" \

+ -s https://api.taiga.io/api/v1/issues?project=325667\&status=2283176

+ """

+ 

file added
+281
@@ -0,0 +1,281 @@ 

+ import requests

+ import json

+ import keyring

+ import os

+ import configparser

+ import editor

+ import bugzilla

+ import lxml.html

+ import os 

+ import re

+ import string

+ import random

+ import jinja2

+ import sys

+ #sys.setdefaultencoding("utf-8")

+ 

+ from tga import epics as tgaepic

+ from tga import issues as tgaissue

+ from tga import userstory as tgauserstory

+ from pgure import issues as pgaissues

+ from bz import bugs as bzbugs

+ from urllib.parse import urlparse

+ from collections import OrderedDict

+ from logger import setup_logging_to_file, log_exception

+ 

+ def sync(x, config):

+     # fvid is fedora version

+     #configpath = args.config

+     #config = configparser.ConfigParser()

+     #config.read(configpath)

+     #fvid = args.sync_status

+     bzapi = bugzilla.Bugzilla(config['BUGZILLA']['BUGZILLA_URL'])

+     #for x in fvid:

+         #config.read('config.ini')

+ 

+     """

+         bzapi = bzapi = bugzilla.Bugzilla(URL)

+         query = bzapi.build_query(

+             component="Changes Tracking",

+             status="NEW",

+             include_fields=["description"])

+         #query["status"] = "NEW"

+         bugs = bzapi.query(query)

+         print(bugs)

+     """

+     print(x)

+     try:

+         r = tgaepic.list_epic(config)

+         if r.status_code == 200:

+             data = json.loads(r.content)

+             #print(data)

+             for i in data:

+                 #print(i['subject'])

+                 if int(i['subject']) == x:

+                     epicid = i['id']

+                     epicref = i['ref']

+                     break

+ 

+                 #url = str(config['TAIGA']['TAIGA_URL']) + "/api/v1/issues/userstories?

+             r = tgaepic.listrelepic_userstory(epicid, config)

+             if r.status_code == 200:

+                 data = json.loads(r.content)

+                 for i in data:

+                     userstoryid = i['user_story']

+                     #print(userstoryid)

+                     try:

+                         r = tgauserstory.get_us(userstoryid, config)

+                         if r.status_code == 200:

+                             userstorydata = json.loads(r.content)

+                             userstory_version = userstorydata['version']

+                             userstoryref = userstorydata['ref']

+                             r = tgauserstory.caget_us(userstoryid, config)

+                             userstorycadata = json.loads(r.content)

+                             bztracker = userstorycadata['attributes_values'][config['TAIGA']['USERSTORY_CA_BUGZILLA_TRACKER']]              

+                             bugid = urlparse(bztracker).query.lstrip("id=")

+                             #print(bugid)

+                             bug = bzbugs.get_bug(bugid, bzapi, config) 

+                             if bug.status == 'MODIFIED':

+                                 statusid = config['TAIGA']['USERSTORY_STATUS_TESTABLE']

+                             elif bug.status == 'ON_QA':

+                                 statusid = config['TAIGA']['USERSTORY_STATUS_CODE_COMPLETE']

+                             #elif bug.status == 'VERIFIED':

+                             #elif bug.status == 'RELEASE_PENDING':

+                             elif bug.status == 'CLOSED':

+                                 statusid = config['TAIGA']['USERSTORY_STATUS_ARCHIVED']

+                             else:

+                                 print("failed to fetch bug status")

+                             payload = {

+                                         'status': statusid,

+                                         'version': userstory_version

+                             }

+                             try:

+                                 r = tgauserstory.changestatus_userstory(userstoryid, payload, config)

+                                 if r.status_code == 200:

+                                     print("Sucesfully Synced status from Bugzilla Bug {} to Taiga Userstory {}".format(bug.id, userstoryref))

+                                 else:

+                                     print("Check logs for errors,Unable to Sync",r.content, r.status_code)

+                             except requests.exceptions.RequestException as e:

+                                 print(e)

+                                 log_exception(e)

+                             except Exception as e:

+                                 print(e)

+                                 log_exception(e)

+                         else:

+                             print("Error in fetching user story")

+                     except requests.exceptions.RequestException as e:

+                         print(e)

+                         log_exception(e)

+                     except Exception as e:

+                         print(e)

+                         log_exception(e)

+             else:

+                 print("Unable to fetch epic related user stories,check logs for errors")

+                 

+         else:

+             print("Unable to Sync Check logs", r.content)

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+ 

+ def report(x,config):

+     try:

+         r = tgaepic.list_epic(config)

+         changes = [] 

+         if r.status_code == 200:

+             data = json.loads(r.content)

+             #print(data)

+             for i in data:

+                 #print(i['subject'])

+                 if int(i['subject']) == x:

+                     epicid = i['id']

+                     epicref = i['ref']

+                     break

+ 

+             r = tgaepic.listrelepic_userstory(epicid, config)

+             if r.status_code == 200:

+                 data = json.loads(r.content)

+                 for i in data:

+                     userstoryid = i['user_story']

+                     #print(userstoryid)

+                     try:

+                         r = tgauserstory.get_us(userstoryid, config)

+                         if r.status_code == 200:

+                             userstorydata = json.loads(r.content)

+                             userstory_version = userstorydata['version']

+                             userstoryref = userstorydata['ref']

+                             description = userstorydata['description']

+                             title = userstorydata['subject']

+                             r = tgauserstory.caget_us(userstoryid, config)

+                             userstorycadata = json.loads(r.content)

+                             bztracker = userstorycadata['attributes_values'][config['TAIGA']['USERSTORY_CA_BUGZILLA_TRACKER']]

+                             summary = userstorycadata['attributes_values'][config['TAIGA']['USERSTORY_CA_SUMMARY']]

+                             #owner = userstorycadata['attributes_values'][config['TAIGA']['USERSTORY_CA_OWNERS']]

+                             email = userstorycadata['attributes_values'][config['TAIGA']['USERSTORY_CA_BUGZILLA_CONTACT']]

+                             target = x

+                             type = userstorycadata['attributes_values'][config['TAIGA']['USERSTORY_CA_SYSTEM_WIDE_CHANGE']]

+                             status = userstorydata['status_extra_info']['name']

+                             subject = userstorydata['subject']

+                             #print(type, "this is type")

+                             #record['Updated'] = page.get("last updated")

+                             

+                             status = userstorydata['status']

+                             #changes.append(userstorycadata)

+                             """

+                             Json Rebuilding is required because

+                             config cant pe passed to the template

+                             and since the user story endpoint only

+                             returns the main userstory and we have 

+                             tp call another userstoyr custom attr

+                             endpoint to retrive teh custom atirbutes

+                             all this needs to be clubbed into one json

+                             to be appended to the jinja2 html template

+                             """

+                             reportjson = {"summary": summary, "contact": email,

+                             "fedora_version": x, "bugzillatracker": bztracker, "description": description, 

+                             "type": type, "status": status, "title": subject }

+                             #rjson = json.dumps(reportjson)

+                             """

+                             types = {'sys_change': [], 'self_change': []}

+                             for n in reportjson:

+                                 if n['type'] == True:

+                                     types['sys_change'].append(n)

+                                 else:

+                                     if n['type'] == False:

+                                         types['self_change'].append(n)

+                             """

+                             changes.append(reportjson)

+                         else:

+                             print("Unable to fetch data to generate report, check logs")

+                     except requests.exceptions.RequestException as e:

+                         print(e)

+                         log_exception(e)

+                     except Exception as e:

+                         print(e)

+                         log_exception(e)

+                 """      

+                 for n in changes:

+                     #print(n['attributes_values'][config['TAIGA']['USERSTORY_CA_SUMMARY']])     

+                     print(n)

+                 """

+                 #print(changes)

+                 try:

+                     templateLoader = jinja2.FileSystemLoader(searchpath="./" )

+                     #print("this step first before that")

+                     templateEnv = jinja2.Environment( loader=templateLoader )

+                     template = templateEnv.get_template("tplate1.html")

+                     #print("this step")

+                     templateVars = {'changes': changes, 'fedoraversion': x}

+                     #print(templateVars)

+                     outputText = template.render(templateVars)

+                     #print(outputText)

+                     with open("test.html", "w") as rhtml:

+                         rhtml.write(outputText)

+                 except Exception as e:

+                     print(e)

+                     log_exception(e)

+             else:

+                 print("Failed to fetch data from taiga to generate report")           

+         else:

+             print("Failed to fetch epics and realted userstories")    

+     except requests.exceptions.RequestException as e:

+         print(e)

+         log_exception(e)

+     except Exception as e:

+         print(e)

+         log_exception(e)

+         

+ 

+         """

+         r = tgaepic.listrelepic_userstory(epicid, config)

+         if r.status_code == 200:

+ 

+             r = tgauserstory.get_us(userstoryid, config)

+             if r.status_code == 200:

+                 userstorydata = json.loads(r.content)

+                 userstory_version = userstorydata['version']

+                 userstoryref = userstorydata['ref']

+                 r = tgauserstory.caget_us(userstoryid, config)

+                 userstorycadata = json.loads(r.content)

+                 bztracker = userstorycadata['attributes_values'][config['TAIGA']['USERSTORY_CA_BUGZILLA_TRACKER']]

+         """

+ 

+ 

+ def update(args):

+     configpath = args.config

+     config = configparser.ConfigParser()

+     config.read(configpath)

+     service_id = config['TAIGA']['SERVICE_ID']  # service id

+     service_token = config['TAIGA']['SERVICE_TOKEN']

+     project_id = config['TAIGA']['PROJECT_ID']

+     log = config['LOG']['LOCATION']

+     setup_logging_to_file(log)

+     fedora_version = args.release

+     for x in fedora_version:

+         try:

+             status = sync(x, config)

+         #status = True

+             if status == True:

+                 print("Succesufully Synced Bugzilla and Taiga status")

+                 print("Generating Report Now .......")

+                 report(x, config)

+             else:

+                 print("Failed to Sync bugzilla and Taiga Status Check logs")

+                 print("Failed to Generate Report")

+         except Exception as e:

+             print(e)

+             log_exception(e)

+ 

+ """

+ if __name__ == "__main__":

+     sync()

+ """

+ """

+ https://overiq.com/flask-101/basics-of-jinja-template-language/

+ https://www.shellhacks.com/jinja2-check-if-variable-empty-exists-defined-true/

+ http://zetcode.com/python/jinja/

+ https://medium.com/@mikaelagurney/add-dynamic-components-to-your-html-templates-using-form-s-flask-and-jinja-59b4169ec3e1

+ """ 

\ No newline at end of file

This pr shows the work done till final evaluation of gsoc,this is not the final status of the project and some more features,code cleanup is in progress that shall last beyond the timeline of gsoc.

Goals Accomplished :
Functionality to Accept the Change Proposals and automatically sync them with Pagure/Bugzilla
Functionality to Create proposals from the cli and a release engineering ticket as well
Sync with the mailing lists
Generate a Static HTML report on all the accepted proposals
Epic mapping Sync as per the attributes in proposals
Documentation both for The users and for further development/maintenance.
Much more smaller functionalities,issues as per the milestones/roadmap
https://www.pagure.io/fedora-change-wrangler/roadmap

Commit a0a4b16 fixes this pull-request

Pull-Request has been merged by pac23

4 years ago

Pull-Request has been merged by pac23

4 years ago
Metadata
Changes Summary 46
+2
file added
.gitignore
+10
file added
Docs/antora.yml
+90
file added
Docs/build.sh
+1
file added
Docs/modules/ROOT/nav.adoc
+34
file added
Docs/modules/ROOT/pages/Accept/accepting-changes.adoc
+38
file added
Docs/modules/ROOT/pages/Announce/announce-mailinglist.adoc
+11
file added
Docs/modules/ROOT/pages/Auth/authenticate-bugzilla.adoc
+32
file added
Docs/modules/ROOT/pages/Auth/authenticate-pagure.adoc
+35
file added
Docs/modules/ROOT/pages/Auth/authenticate-taiga.adoc
+47
file added
Docs/modules/ROOT/pages/Config/Config-set.adoc
+4
file added
Docs/modules/ROOT/pages/Config/config-note.adoc
+29
file added
Docs/modules/ROOT/pages/Convert/convert.adoc
+6
file added
Docs/modules/ROOT/pages/Developer Documentation/Bugzilla/Bugzilla-dev.adoc
+6
file added
Docs/modules/ROOT/pages/Developer Documentation/Config/config-dev.adoc
+7
file added
Docs/modules/ROOT/pages/Developer Documentation/Mailing/mailing-list.adoc
+11
file added
Docs/modules/ROOT/pages/Developer Documentation/Pagure/pagure-dev.adoc
+19
file added
Docs/modules/ROOT/pages/Developer Documentation/Taiga/taiga-dev.adoc
+23
file added
Docs/modules/ROOT/pages/Fesco/fesco.adoc
+0
file added
Docs/modules/ROOT/pages/List/List-Userstories
+22
file added
Docs/modules/ROOT/pages/List/list.adoc
+17
file added
Docs/modules/ROOT/pages/Sync/sync-status.adoc
+35
file added
Docs/preview.sh
+40
file added
Docs/site.yml
+46
file added
ReadMe.md
+0
file added
__init__.py
+144
file added
accept.py
+62
file added
bz/bugs.py
+56
file added
bz/bugzilla_auth.py
+170
file added
bz/pgba.py
+94
file added
config.ini
+118
file added
mail/climail.py
+32
file added
mail/mailauth.py
+94
file added
mail/maillist.py
+252 -20
file changed
main.py
+104
file added
notes/notes.txt
+114
file added
pgure/fesco.py
+91
file added
pgure/issues.py
+34
file added
pgure/pagure_auth.py
+71
file added
requirements.txt
+245
file added
tga/convert.py
+143
file added
tga/createprop.py
+105
file added
tga/epics.py
+239
file added
tga/issues.py
+122
file added
tga/taiga_auth.py
+247
file added
tga/userstory.py
+281
file added
update.py