diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 04573a1..0a467da 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -24,14 +24,25 @@ jobs: with: python-version: 3.8.6 + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Install Gauge uses: getgauge/setup-gauge@master with: gauge-version: master - gauge-plugins: python, html-report + gauge-plugins: python, html-report, screenshot - name: FTs - run: gauge run specs + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_ADMIN_USERNAME: ${{ secrets.JIRA_ADMIN_USERNAME }} + JIRA_ADMIN_PASSWORD: ${{ secrets.JIRA_ADMIN_PASSWORD }} + INTERNAL_EMPLOYEE_USERNAME: ${{ secrets.INTERNAL_EMPLOYEE_USERNAME }} + INTERNAL_EMPLOYEE_PASSWORD: ${{ secrets.INTERNAL_EMPLOYEE_PASSWORD }} + run: gauge run specs --tags \!in-progress - name: Upload logs uses: actions/upload-artifact@v2.2.2 diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index fb66ea6..fbbe4f2 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -82,7 +82,7 @@ jobs: **/*.spec **/*.txt language: en - disabled_rules: "DOUBLE_PUNCTUATION,WHITESPACE_RULE,EN_QUOTES,DASH_RULE,WORD_CONTAINS_UNDERSCORE,UPPERCASE_SENTENCE_START,ARROWS,COMMA_PARENTHESIS_WHITESPACE,UNLIKELY_OPENING_PUNCTUATION,SENTENCE_WHITESPACE,CURRENCY,EN_UNPAIRED_BRACKETS,PHRASE_REPETITION,PUNCTUATION_PARAGRAPH_END,METRIC_UNITS_EN_US,ENGLISH_WORD_REPEAT_BEGINNING_RULE,GITHUB" # yamllint disable-line + disabled_rules: "DOUBLE_PUNCTUATION,WHITESPACE_RULE,EN_QUOTES,DASH_RULE,WORD_CONTAINS_UNDERSCORE,UPPERCASE_SENTENCE_START,ARROWS,COMMA_PARENTHESIS_WHITESPACE,UNLIKELY_OPENING_PUNCTUATION,SENTENCE_WHITESPACE,CURRENCY,EN_UNPAIRED_BRACKETS,PHRASE_REPETITION,PUNCTUATION_PARAGRAPH_END,METRIC_UNITS_EN_US,ENGLISH_WORD_REPEAT_BEGINNING_RULE,GITHUB,A_NNS" # yamllint disable-line black: # Black is an opinionated Python linter name: runner / black formatter diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a2ffc47..e08d26d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,41 +3,20 @@ Firstly thanks for thinking of contributing - the project is [open source](https://opensource.guide/how-to-contribute/) and all contributions are very welcome :slightly_smiling_face: :boom: :thumbsup: -[How to make a contribution](#how-to-make-a-contribution) - -[Local development](#local-development) - -* [Visual Studio Code](#visual-studio-code) -* [Codespaces](#codespaces) -* [Tools and technologies](#tools-and-technologies) - -## How to make a contribution - -* [Create a pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests). -The project uses the _[fork and pull model](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-collaborative-development-models)_: - * [Fork the project](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks) - * Make your changes on your fork - * Write a [good commit message(s)](https://chris.beams.io/posts/git-commit/) for your changes - * [Create the pull request for your changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests) - ## Local development -### Visual Studio Code +### VS Code -The easiest way to set up your development environment (unless you have [Codespaces](#codespaces), which is even easier) -is to use [Visual Studio Code](https://code.visualstudio.com/)'s [Remote Containers](https://code.visualstudio.com/docs/remote/containers) -functionality: +The preferred development environment is on a [Visual Studio Code](https://code.visualstudio.com/) [Remote Container](https://code.visualstudio.com/docs/remote/containers) +(as this comes fully loaded with the right software and code linters etc). * [System requirements](https://code.visualstudio.com/docs/remote/containers#_system-requirements) + * [Visual Studio Code](https://code.visualstudio.com/) + * [Docker Desktop](https://www.docker.com/products/docker-desktop) * [Fork the project](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks) -* [Open the local project folder in a container](https://code.visualstudio.com/docs/remote/containers#_quick-start-open-an-existing-folder-in-a-container) -* Everything will then be setup for you. +* [Open the forked repo (or a specific branch or pull request) in a VS Code container](https://code.visualstudio.com/docs/remote/containers#_quick-start-open-a-git-repository-or-github-pr-in-an-isolated-container-volume) -### Codespaces - -If you have access to [GitHub Codespaces](https://github.com/features/codespaces/) (which allows full remote -development from within your browser) then all you need to do is [fork the project](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks) -and open it in Codespaces - easy! + The remote VS Code container will start with all the software you need installed and configured correctly. ### Tools and technologies @@ -47,6 +26,37 @@ and open it in Codespaces - easy! * [Flake8](https://flake8.pycqa.org/) for Python style checks * [GitHub Actions](https://docs.github.com/en/actions) for CI +### Environment configuration + +You will need to set up some Gauge properties: + +1. Create the following file: `env/default/secrets.properties` +2. Populate the file with: + + ```lang-default + JIRA_BASE_URL = + JIRA_ADMIN_USERNAME = + JIRA_ADMIN_PASSWORD = + INTERNAL_EMPLOYEE_USERNAME = + INTERNAL_EMPLOYEE_PASSWORD = + ``` + +3. Ask [a maintainer](.github/CODEOWNERS) for the values for the above configuration properties and populate them in + the file you just created. + +### Running the specs + +`gauge run --tags \!in-progress` + +## How to make a contribution + +* [Create a pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests). +The project uses the _[fork and pull model](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-collaborative-development-models)_: + * [Fork the project](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks) + * Make your changes on your fork + * Write a [good commit message(s)](https://chris.beams.io/posts/git-commit/) for your changes + * [Create the pull request for your changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests) + ## Updating dependencies See the [DEPENDENCIES.md](.github/DEPENDENCIES.md) diff --git a/README.md b/README.md index f670f58..53af95f 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ Verifies a Jira configuration through executable specifications +[How to run the specs](CONTRIBUTING.md#local-development) + ## Suggestions / bug reports / contributions The project is [open source](https://opensource.guide/how-to-contribute/) and all contributions are very welcome :slightly_smiling_face: :boom: :thumbsup: -* [How to report a bug or suggest a new feature](CONTRIBUTING.md#how-to-report-a-bug-or-suggest-a-new-feature) - * [How to contribute](CONTRIBUTING.md#how-to-make-a-contribution) diff --git a/requirements.txt b/requirements.txt index dccbded..5d80d03 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ getgauge +jira diff --git a/specs/example.spec b/specs/example.spec deleted file mode 100644 index 80886a6..0000000 --- a/specs/example.spec +++ /dev/null @@ -1,33 +0,0 @@ -# Specification Heading - -This is an executable specification file. This file follows Markdown syntax. -Every heading in this file denotes a scenario. Every bulleted point denotes a step. - -To execute this specification, run - - gauge run specs - - -* Vowels in English language are "aeiou". - -## Vowel counts in single word - -tags: single word - -* The word "gauge" has "3" vowels. - - -## Vowel counts in multiple word - -This is the second scenario in this specification - -Here's a step that takes a table - -* Almost all words have vowels - |Word |Vowel Count| - |------|-----------| - |Gauge |3 | - |Mingle|2 | - |Snap |1 | - |GoCD |1 | - |Rhythm|0 | diff --git a/specs/group_membership.spec b/specs/group_membership.spec new file mode 100644 index 0000000..325e6b1 --- /dev/null +++ b/specs/group_membership.spec @@ -0,0 +1,8 @@ +# Group membership + +Our implementation of group membership rules is based on +https://www.atlassian.com/blog/archives/share-jira-external-partners + +## All employees are members of the internal employees group + +* An internal employee is a member of the internal employees group diff --git a/specs/groups.spec b/specs/groups.spec new file mode 100644 index 0000000..ad59b7f --- /dev/null +++ b/specs/groups.spec @@ -0,0 +1,10 @@ +# Groups + +Our groups are based on the ideas in +https://www.atlassian.com/blog/archives/share-jira-external-partners + +## There is an internal employees group + +This group is for all internal employees who currently need access to this Jira instance + +* There is a jira-internal-employee-users group diff --git a/specs/project_visibility.spec b/specs/project_visibility.spec new file mode 100644 index 0000000..9e51969 --- /dev/null +++ b/specs/project_visibility.spec @@ -0,0 +1,25 @@ +# Project visibility + +Our implementation of project visibility rules is based on +https://www.atlassian.com/blog/archives/share-jira-external-partners + +## All internal employees can see all projects + +This is in line with our [InnerSource](https://about.gitlab.com/solutions/innersource/) principles. + +* An internal employee can see all projects + +## All external partners can only see the projects they are currently working on + +tags: in-progress + +Question: what about individual contractors, as opposed to external partner companies? + +* Not implemented yet + +## Closed projects are no longer viewable by any external partners + +tags: in-progress + +* Not implemented yet + diff --git a/step_impl/bot.py b/step_impl/bot.py new file mode 100644 index 0000000..1221657 --- /dev/null +++ b/step_impl/bot.py @@ -0,0 +1,24 @@ +from getgauge.python import before_suite +from step_impl.jira import Jira +import os + +JIRA_BASE_URL = os.getenv("JIRA_BASE_URL") +JIRA_ADMIN_USERNAME = os.getenv("JIRA_ADMIN_USERNAME") +JIRA_ADMIN_PASSWORD = os.getenv("JIRA_ADMIN_PASSWORD") +INTERNAL_EMPLOYEE_USERNAME = os.getenv("INTERNAL_EMPLOYEE_USERNAME") +INTERNAL_EMPLOYEE_PASSWORD = os.getenv("INTERNAL_EMPLOYEE_PASSWORD") +INTERNAL_EMPLOYEES_GROUP = "jira-internal-employee_users" + + +class Bot(object): + jira_admin = None + internal_employee = None + + @before_suite + def init(self): + Bot.jira_admin = Jira(JIRA_BASE_URL, JIRA_ADMIN_USERNAME, JIRA_ADMIN_PASSWORD) + Bot.internal_employee = Jira( + JIRA_BASE_URL, + INTERNAL_EMPLOYEE_USERNAME, + INTERNAL_EMPLOYEE_PASSWORD, + ) diff --git a/step_impl/jira.py b/step_impl/jira.py new file mode 100644 index 0000000..0874e79 --- /dev/null +++ b/step_impl/jira.py @@ -0,0 +1,20 @@ +from jira import JIRA + + +class Jira: + def __init__(self, base_url, username, password): + self.jira = JIRA( + auth=(username, password), + options={"server": base_url}, + ) + self.username = username + + def has_group(self, group_name): + return len(self.jira.group_members(group_name)) >= 0 + + def projects(self): + return self.jira.projects() + + def is_user_in_group(self, user, group): + group_members = self.jira.group_members(group) + return bool([emp for emp in group_members.values() if (emp["name"] == user)]) diff --git a/step_impl/step_impl.py b/step_impl/step_impl.py index a7a0e08..42df42b 100644 --- a/step_impl/step_impl.py +++ b/step_impl/step_impl.py @@ -1,45 +1,24 @@ -from getgauge.python import step, before_scenario, Messages +from getgauge.python import step +from step_impl.bot import Bot, INTERNAL_EMPLOYEES_GROUP -vowels = ["a", "e", "i", "o", "u"] +@step("An internal employee can see all projects") +def an_internal_employee_can_see_all_projects(): + assert len(Bot.internal_employee.projects()) == len(Bot.jira_admin.projects()) -def number_of_vowels(word): - return len([elem for elem in list(word) if elem in vowels]) +@step("An internal employee is a member of the internal employees group") +def an_internal_employee_is_a_member_of_the_internal_employees_group(): + assert Bot.jira_admin.is_user_in_group( + Bot.internal_employee.username, INTERNAL_EMPLOYEES_GROUP + ) -# -------------------------- -# Gauge step implementations -# -------------------------- +@step("There is a jira-internal-employee-users group") +def there_is_a_jira_internal_employee_users_group(): + assert Bot.jira_admin.has_group(INTERNAL_EMPLOYEES_GROUP) -@step("The word has vowels.") -def assert_no_of_vowels_in(word, number): - assert str(number) == str(number_of_vowels(word)) - -@step("Vowels in English language are .") -def assert_default_vowels(given_vowels): - Messages.write_message("Given vowels are {0}".format(given_vowels)) - assert given_vowels == "".join(vowels) - - -@step("Almost all words have vowels ") -def assert_words_vowel_count(table): - actual = [ - str(number_of_vowels(word)) - for word in table.get_column_values_with_name("Word") - ] - expected = [ - str(count) for count in table.get_column_values_with_name("Vowel Count") - ] - assert expected == actual - - -# --------------- -# Execution Hooks -# --------------- - - -@before_scenario() -def before_scenario_hook(): - assert "".join(vowels) == "aeiou" +@step("Not implemented yet") +def not_implemented_yet(): + assert False, "Add implementation code"