diff --git a/.github/workflows/add-issue-to-projects.yml b/.github/workflows/add-issue-to-projects.yml index c778ea15b0..48c8b6e0a2 100644 --- a/.github/workflows/add-issue-to-projects.yml +++ b/.github/workflows/add-issue-to-projects.yml @@ -1,4 +1,5 @@ -name: Add Issue To Projects +name: "[Issue Management] Add Issue To Projects" + on: issues: types: [opened] diff --git a/.github/workflows/auto-author-assign.yml b/.github/workflows/auto-author-assign.yml index 2837abbb9e..2a6507d4e0 100644 --- a/.github/workflows/auto-author-assign.yml +++ b/.github/workflows/auto-author-assign.yml @@ -1,4 +1,4 @@ -name: Auto Author Assign +name: "[PR Management] Auto Author Assign" on: workflow_call: diff --git a/.github/workflows/backport-pr.yml b/.github/workflows/backport-pr.yml index c467e4444a..e4313f6987 100644 --- a/.github/workflows/backport-pr.yml +++ b/.github/workflows/backport-pr.yml @@ -1,4 +1,4 @@ -name: Link-Backport-PR-Issue +name: "[Issue Management] Link Backport PR Issue" on: pull_request: diff --git a/.github/workflows/close-issue.yml b/.github/workflows/close-issue.yml index 64f643c020..a79461e695 100644 --- a/.github/workflows/close-issue.yml +++ b/.github/workflows/close-issue.yml @@ -1,4 +1,4 @@ -name: Close-Issue +name: "[Issue Management] Close Issue" on: issues: types: [ unlabeled ] diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 9327413c58..2cd7f88639 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -1,4 +1,4 @@ -name: Codespell +name: "[PR Management] Codespell" on: pull_request: diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml index 20ed492ec2..f11ce5f4df 100644 --- a/.github/workflows/conventional-commits.yml +++ b/.github/workflows/conventional-commits.yml @@ -1,4 +1,4 @@ -name: Conventional Commits +name: "[PR Management] Conventional PR and Commits" on: pull_request_target: diff --git a/.github/workflows/create-issue.yml b/.github/workflows/create-issue.yml index 5248ad0d90..604603c71a 100644 --- a/.github/workflows/create-issue.yml +++ b/.github/workflows/create-issue.yml @@ -1,4 +1,4 @@ -name: Create-Issue +name: "[Issue Management] Create Issue" on: issues: types: [ labeled ] diff --git a/.github/workflows/create-release-task-issues.yml b/.github/workflows/create-release-task-issues.yml index 2dccc3c15d..0c69dd22a2 100644 --- a/.github/workflows/create-release-task-issues.yml +++ b/.github/workflows/create-release-task-issues.yml @@ -1,4 +1,4 @@ -name: Create Release Task Issues +name: "[Release] Create Release Task Issues" on: workflow_dispatch: diff --git a/.github/workflows/migrate-zenhub-board-to-github-project.py b/.github/workflows/migrate-zenhub-board-to-github-project.py deleted file mode 100644 index 7fa9b1da40..0000000000 --- a/.github/workflows/migrate-zenhub-board-to-github-project.py +++ /dev/null @@ -1,383 +0,0 @@ -import requests -import os -import jq -import sys -import time - - -GITHUB_API_URL = "https://api.github.com" -GITHUB_GRAPHQL_URL = "https://api.github.com/graphql" -ZENHUB_API_URL = "https://api.zenhub.com/p1/repositories/{repo_id}/board" - - -def get_github_repo_id(github_token, github_org, github_repo): - url = f"{GITHUB_API_URL}/repos/{github_org}/{github_repo}" - headers = { - "Authorization": github_token - } - - response = requests.get(url, headers=headers) - if response.status_code == 200: - return response.json().get("id") - else: - response.raise_for_status() - - -def get_zenhub_board(zenhub_token, github_repo_id): - url = ZENHUB_API_URL.format(repo_id=github_repo_id) - headers = { - "Content-Type": "application/json", - "X-Authentication-Token": zenhub_token - } - - response = requests.get(url, headers=headers) - if response.status_code == 200: - return response.json() - else: - response.raise_for_status() - - -def get_github_issue(github_token, github_org, github_repo, issue_number): - url = f"https://api.github.com/repos/{github_org}/{github_repo}/issues/{issue_number}" - headers = { - "Authorization": f"token {github_token}", - "Accept": "application/vnd.github.v3+json" - } - - response = requests.get(url, headers=headers) - if response.status_code == 200: - return response.json() - else: - response.raise_for_status() - - -def get_github_project(github_token, github_org, github_repo, project_number): - headers = { - "Authorization": f"Bearer {github_token}", - "Content-Type": "application/json" - } - query = ''' - query { - repository(owner: "%s", name: "%s") { - projectV2(number: %d) { - id - title - fields(first: 20) { - nodes { - ... on ProjectV2FieldCommon { - id - name - } - ... on ProjectV2SingleSelectField { - id - name - options { - id - name - } - } - } - } - } - } - } - ''' % (github_org, github_repo, project_number) - payload = { - "query": query - } - - response = requests.post(GITHUB_GRAPHQL_URL, headers=headers, json=payload) - if response.status_code == 200: - return response.json().get("data").get("repository").get("projectV2") - else: - response.raise_for_status() - - -def get_github_project_status(github_token, github_org, github_repo, project_number): - project = get_github_project(github_token, github_org, github_repo, project_number) - nodes = project.get("fields").get("nodes") - for node in nodes: - if node.get("name") == "Status": - return node.get("id"), {option.get("name"): option.get("id") for option in node.get("options")} - - -def get_github_project_estimate(github_token, github_org, github_repo, project_number): - project = get_github_project(github_token, github_org, github_repo, project_number) - nodes = project.get("fields").get("nodes") - for node in nodes: - if node.get("name") == "Estimate": - return node.get("id") - - -def get_github_project_info(github_token, github_org, github_project): - headers = { - "Authorization": f"Bearer {github_token}", - "Content-Type": "application/json" - } - query = ''' - { - organization(login: "%s") { - projectsV2(first: 20) { - nodes { - id - title - number - } - } - } - } - ''' % (github_org) - payload = { - "query": query - } - - response = requests.post(GITHUB_GRAPHQL_URL, headers=headers, json=payload) - print(f"GitHub Project Info: {response.json()}") - if response.status_code == 200: - # fine project by title - nodes = response.json().get("data").get("organization").get("projectsV2").get("nodes") - print(f"Nodes: {nodes}") - - for node in nodes: - print(f"Node: {node}") - print(f"Title: {node.get('title')}") - print(f"GitHub Project: {github_project}") - if node.get("title") == github_project: - return node - else: - response.raise_for_status() - - -def add_github_project_item(github_token, project_id, content_id): - headers = { - "Authorization": f"Bearer {github_token}", - "Content-Type": "application/json" - } - query = ''' - mutation { - addProjectV2ItemById(input: {projectId: "%s", contentId: "%s"}) { - item { - id - } - } - } - ''' % (project_id, content_id) - payload = { - "query": query - } - - response = requests.post(GITHUB_GRAPHQL_URL, headers=headers, json=payload) - return response.json() - - -def move_item_to_status(github_token, project_id, item_id, field_id, single_select_option_id): - headers = { - "Authorization": f"Bearer {github_token}", - "Content-Type": "application/json" - } - query = ''' - mutation { - updateProjectV2ItemFieldValue(input: {projectId: "%s", itemId: "%s", fieldId: "%s", value: {singleSelectOptionId: "%s"}}) { - projectV2Item { - id - } - } - } - ''' % (project_id, item_id, field_id, single_select_option_id) - payload = { - "query": query - } - - response = requests.post(GITHUB_GRAPHQL_URL, headers=headers, json=payload) - if response.status_code == 200: - return response.json() - else: - response.raise_for_status() - - -def set_item_estimate(github_token, project_id, item_id, field_id, value): - headers = { - "Authorization": f"Bearer {github_token}", - "Content-Type": "application/json" - } - query = f''' - mutation {{ - updateProjectV2ItemFieldValue(input: {{projectId: "{project_id}", itemId: "{item_id}", fieldId: "{field_id}", value: {{number: {value}}}}}) {{ - projectV2Item {{ - id - }} - }} - }} - ''' - payload = { - "query": query - } - - response = requests.post(GITHUB_GRAPHQL_URL, headers=headers, json=payload) - if response.status_code == 200: - return response.json() - else: - response.raise_for_status() - - -def get_github_issues(github_token, github_org, github_repo, state): - url = f"https://api.github.com/repos/{github_org}/{github_repo}/issues" - headers = { - "Authorization": f"token {github_token}", - "Accept": "application/vnd.github.v3+json" - } - params = { - "state": "closed", - "per_page": 100, - "page": 1 - } - - all_issues = [] - while True: - response = requests.get(url, headers=headers, params=params) - if response.status_code != 200: - raise Exception(f"Error fetching issues: {response.status_code} {response.text}") - - issues = response.json() - if not issues: - break - - all_issues.extend(issues) - params["page"] += 1 - - return all_issues - - -def get_zenhub_issue_info(zenhub_token, github_repo_id, issue_number): - url = f"https://api.zenhub.com/p1/repositories/{github_repo_id}/issues/{issue_number}" - headers = { - "X-Authentication-Token": zenhub_token, - "Accept": "application/json" - } - - response = requests.get(url, headers=headers) - - if response.status_code == 200: - return response.json() - elif response.status_code == 403: - print("Rate limit exceeded. Sleeping for 1 minute") - else: - response.raise_for_status() - - -def check_zenhub_pipelins_github_project_status_match(board, status): - zenhub_pipelines = [pipeline['name'] for pipeline in board['pipelines']] - github_project_statuses = list(status.keys()) - for pipeline in zenhub_pipelines: - if pipeline not in github_project_statuses: - raise Exception(f"Pipeline '{pipeline}' not found in GitHub Project statuses") - - -def add_closed_issues_to_github_project(github_token, zenhub_token, github_org, github_repo, project_id, status, status_node_id, estimate_node_id): - github_repo_id = get_github_repo_id(github_token, github_org, github_repo) - issues = get_github_issues(github_token, github_org, github_repo, "closed") - - print(f"Found {len(issues)} closed issues in the GitHub repo") - - for issue in issues: - print(f"Processing closed issue: {issue['number']}") - - # Exclude PRs to the project - if 'pull_request' not in issue: - result = add_github_project_item(github_token, project_id, issue['node_id']) - print(f"Added issue: result={result}") - - item_id = result['data']['addProjectV2ItemById']['item']['id'] - move_item_to_status(github_token, - project_id, item_id, - status_node_id, - status['Closed']) - - zenhub_issue = get_zenhub_issue_info(zenhub_token, github_repo_id, issue['number']) - print(f"ZenHub Issue Info: {zenhub_issue}") - - # check if estimate is exist - if 'estimate' in zenhub_issue: - print(f"Setting estimate: {zenhub_issue['estimate'].get('value')} for issue: {issue['number']}") - set_item_estimate(github_token, - project_id, item_id, - estimate_node_id, zenhub_issue['estimate'].get('value')) - # Sleep for 2 seconds to avoid rate limiting - time.sleep(2) - - -def add_zenhub_pipelines_to_github_project(github_token, github_org, github_repo, project_id, board, status, status_node_id, estimate_node_id): - for pipeline in board['pipelines']: - # Iterating through each pipeline, which are corresponding to the GitHub Project statuses (columns) - column_name = pipeline['name'] - - # Iterating through each ticket in the pipeline, - # and creating a corresponding GitHub issue - - for issue in pipeline['issues']: - print("Issue: ", issue) - print(f"Processing issue: {issue['issue_number']} in pipeline: {column_name}") - issue_info = get_github_issue(github_token, github_org, github_repo, - issue['issue_number']) - result = add_github_project_item(github_token, - project_id, issue_info['node_id']) - print(f"Added issue: result={result}") - item_id = result['data']['addProjectV2ItemById']['item']['id'] - move_item_to_status(github_token, - project_id, item_id, - status_node_id, - status[column_name]) - # check if estimate is exist - if 'estimate' in issue: - print(f"Setting estimate: {issue['estimate'].get('value')} for issue: {issue['issue_number']}") - set_item_estimate(github_token, - project_id, item_id, - estimate_node_id, issue['estimate'].get('value')) - -def migrate_tickets(github_org, github_repo, github_project): - github_token = os.getenv("GITHUB_TOKEN") - zenhub_token = os.getenv("ZENHUB_TOKEN") - - # Get the GitHub Project details - project = get_github_project_info(github_token, github_org, github_project) - print(f"GitHub Project Details: {project}") - project_number = project.get("number") - project_id = project.get("id") - status_node_id, status = get_github_project_status(github_token, github_org, github_repo, project_number) - print(f"GitHub Project Details: number={project_number}, id={project_id}, status node_id={status_node_id}, status={status}") - - estimate_node_id = get_github_project_estimate(github_token, github_org, github_repo, project_number) - print(f"GitHub Project Details: number={project_number}, id={project_id}, estimate node_id={estimate_node_id}") - - # Get the ZenHub board details - github_repo_id = get_github_repo_id(github_token, github_org, github_repo) - print(f"GitHub Repo ID: {github_repo_id}") - board = get_zenhub_board(zenhub_token, github_repo_id) - for pipeline in board['pipelines']: - print(f"Pipeline: {pipeline}") - - # Check pipelines of the ZenHub board and status of the GitHub Project are matching using for loop - check_zenhub_pipelins_github_project_status_match(board, status) - - # Add ZenHub pipelines to the GitHub Project Statuses - add_zenhub_pipelines_to_github_project(github_token, - github_org, github_repo, - project_id, - board, - status, status_node_id, - estimate_node_id) - - # ZenHub doesn't have closed pipeline, so we need to iterate through all closed issues in the GitHub repo. - add_closed_issues_to_github_project(github_token, zenhub_token, - github_org, github_repo, - project_id, - status, status_node_id, - estimate_node_id) - - -if __name__ == "__main__": - if len(sys.argv) < 4: - print('Usage: python migrate-zenhub-board-to-github-project.py ') - sys.exit() - - migrate_tickets(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/.github/workflows/migrate-zenhub-board-to-github-project.yml b/.github/workflows/migrate-zenhub-board-to-github-project.yml deleted file mode 100644 index 8ad0f4c9f6..0000000000 --- a/.github/workflows/migrate-zenhub-board-to-github-project.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Migrate ZenHub Board to GitHub Project - -on: - workflow_dispatch: - inputs: - github_org: - description: "GitHub organization" - default: "longhorn" - required: true - github_repo: - description: "GitHub repository" - default: "longhorn" - required: true - github_project: - description: "GitHub project" - default: "Longhorn Sprint" - required: true -jobs: - migrate: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Install dependencies - run: | - python -m pip install requests jq - - - name: Migrate ZenHub Board to GitHub Project - env: - ZENHUB_TOKEN: ${{ secrets.ZENHUB_TOKEN }} - GITHUB_TOKEN: ${{ secrets.CUSTOM_GITHUB_TOKEN }} - run: | - python ./.github/workflows/migrate-zenhub-board-to-github-project.py "${{ inputs.github_org }}" "${{ inputs.github_repo }}" "${{ inputs.github_project }}" diff --git a/.github/workflows/periodic-issue-sprint-update.yml b/.github/workflows/periodic-issue-sprint-update.yml index 05229a2dc7..581f3126cf 100644 --- a/.github/workflows/periodic-issue-sprint-update.yml +++ b/.github/workflows/periodic-issue-sprint-update.yml @@ -1,4 +1,4 @@ -name: Periodic Issue Sprint Update +name: "[Issue Management] Periodic Issue Sprint Update" on: schedule: diff --git a/.github/workflows/scan-and-notify-testing-items.yml b/.github/workflows/scan-and-notify-testing-items.yml index 2493d0909d..da4636530f 100644 --- a/.github/workflows/scan-and-notify-testing-items.yml +++ b/.github/workflows/scan-and-notify-testing-items.yml @@ -1,4 +1,4 @@ -name: Scan and Notify Testing Items +name: "[Notification] Scan and Notify Testing Items" on: schedule: diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index bb71fd83c0..b047fdc3f6 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -1,4 +1,4 @@ -name: Scorecard supply-chain security +name: "[Security] Scorecard Supply-Chain Security" on: # For Branch-Protection check. Only the default branch is supported. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 4abcd47ca1..579bf849ef 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -1,4 +1,4 @@ -name: 'Close stale issues and PRs' +name: "[Issue Management] Close Stale Issues and PRs" on: workflow_call: diff --git a/.github/workflows/update-branch-image-tags.yaml b/.github/workflows/update-branch-image-tags.yaml index d08880250c..4f2272710d 100644 --- a/.github/workflows/update-branch-image-tags.yaml +++ b/.github/workflows/update-branch-image-tags.yaml @@ -1,4 +1,4 @@ -name: Update Longhorn Repository Branch Image Tags +name: "[Release] Update Longhorn Repository Branch Image Tags" on: workflow_dispatch: diff --git a/.github/workflows/update-community-review-sprint-issue-status.yaml b/.github/workflows/update-community-review-sprint-issue-status.yaml index ece03c61fd..6f72275bbd 100644 --- a/.github/workflows/update-community-review-sprint-issue-status.yaml +++ b/.github/workflows/update-community-review-sprint-issue-status.yaml @@ -1,4 +1,4 @@ -name: Update Community Review Sprint Issue Status +name: "[Issue Management] Update Community Review Sprint Issue Status" on: issues: types: [labeled, milestoned, reopened, closed] diff --git a/.github/workflows/validate-yamls.yaml b/.github/workflows/validate-yamls.yaml index e304c31f37..aee34c8ae0 100644 --- a/.github/workflows/validate-yamls.yaml +++ b/.github/workflows/validate-yamls.yaml @@ -1,4 +1,4 @@ -name: Validate Longhorn YAMLs +name: "[PR Management] Validate Longhorn YAMLs" on: pull_request_target: diff --git a/.github/workflows/wont-fix.yml b/.github/workflows/wont-fix.yml index 9a9694a247..5a85bfe624 100644 --- a/.github/workflows/wont-fix.yml +++ b/.github/workflows/wont-fix.yml @@ -1,4 +1,4 @@ -name: Add-Wontfix-Label-To-Not-Planned-Issue +name: "[Issue Management] Add Wontfix Label To Not-Planned Issue" on: issues: diff --git a/chart/README.md b/chart/README.md index ba05dbf10b..62fcfc9451 100644 --- a/chart/README.md +++ b/chart/README.md @@ -100,7 +100,7 @@ The `values.yaml` contains items used to tweak a deployment of this chart. | image.csi.nodeDriverRegistrar.repository | string | `"longhornio/csi-node-driver-registrar"` | Repository for the CSI Node Driver Registrar image. When unspecified, Longhorn uses the default value. | | image.csi.nodeDriverRegistrar.tag | string | `"v2.13.0"` | Tag for the CSI Node Driver Registrar image. When unspecified, Longhorn uses the default value. | | image.csi.provisioner.repository | string | `"longhornio/csi-provisioner"` | Repository for the CSI Provisioner image. When unspecified, Longhorn uses the default value. | -| image.csi.provisioner.tag | string | `"v5.1.0-20241220"` | Tag for the CSI Provisioner image. When unspecified, Longhorn uses the default value. | +| image.csi.provisioner.tag | string | `"v5.1.0"` | Tag for the CSI Provisioner image. When unspecified, Longhorn uses the default value. | | image.csi.resizer.repository | string | `"longhornio/csi-resizer"` | Repository for the CSI Resizer image. When unspecified, Longhorn uses the default value. | | image.csi.resizer.tag | string | `"v1.13.1"` | Tag for the CSI Resizer image. When unspecified, Longhorn uses the default value. | | image.csi.snapshotter.repository | string | `"longhornio/csi-snapshotter"` | Repository for the CSI Snapshotter image. When unspecified, Longhorn uses the default value. | @@ -116,7 +116,7 @@ The `values.yaml` contains items used to tweak a deployment of this chart. | image.longhorn.shareManager.repository | string | `"longhornio/longhorn-share-manager"` | Repository for the Longhorn Share Manager image. | | image.longhorn.shareManager.tag | string | `"master-head"` | Tag for the Longhorn Share Manager image. | | image.longhorn.supportBundleKit.repository | string | `"longhornio/support-bundle-kit"` | Repository for the Longhorn Support Bundle Manager image. | -| image.longhorn.supportBundleKit.tag | string | `"v0.0.49"` | Tag for the Longhorn Support Bundle Manager image. | +| image.longhorn.supportBundleKit.tag | string | `"v0.0.53"` | Tag for the Longhorn Support Bundle Manager image. | | image.longhorn.ui.repository | string | `"longhornio/longhorn-ui"` | Repository for the Longhorn UI image. | | image.longhorn.ui.tag | string | `"master-head"` | Tag for the Longhorn UI image. | | image.openshift.oauthProxy.repository | string | `""` | Repository for the OAuth Proxy image. Specify the upstream image (for example, "quay.io/openshift/origin-oauth-proxy"). This setting applies only to OpenShift users. | diff --git a/deploy/longhorn-images.txt b/deploy/longhorn-images.txt index 4d9597245a..9362a7cea6 100644 --- a/deploy/longhorn-images.txt +++ b/deploy/longhorn-images.txt @@ -1,14 +1,14 @@ -longhornio/csi-attacher:v4.8.0 -longhornio/csi-provisioner:v5.1.0-20241220 -longhornio/csi-resizer:v1.13.1 -longhornio/csi-snapshotter:v8.2.0 -longhornio/csi-node-driver-registrar:v2.13.0 -longhornio/livenessprobe:v2.15.0 -longhornio/backing-image-manager:master-head +longhornio/backing-image-manage:master-head longhornio/longhorn-engine:master-head longhornio/longhorn-instance-manager:master-head longhornio/longhorn-manager:master-head longhornio/longhorn-share-manager:master-head longhornio/longhorn-ui:master-head longhornio/longhorn-cli:master-head -longhornio/support-bundle-kit:v0.0.49 +longhornio/csi-attacher:v4.8.0 +longhornio/csi-provisioner:v5.1.0 +longhornio/csi-resizer:v1.13.1 +longhornio/csi-snapshotter:v8.2.0 +longhornio/node-driver-registrar:v2.13.0 +longhornio/livenessprobe:v2.15.0 +longhornio/support-bundle-kit:v0.0.53