├── .github ├── CODEOWNERS ├── release-drafter.yml ├── dependabot.yml └── workflows │ └── release-drafter.yml ├── .gitignore ├── .dockerignore ├── docker ├── favicon.ico ├── default.conf └── index.html ├── Jenkinsfile_k8s ├── compose.yml ├── Makefile ├── Dockerfile ├── LICENSE ├── README.md └── bin └── redirects.sh /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jenkins-infra/core 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | jira-keys-to-github-id-for-external-use* 2 | update.sh 3 | 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !bin/redirects.sh 3 | !mappings/jira_keys_to_github_ids.txt 4 | !docker/* 5 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | _extends: .github 2 | 3 | name-template: 'next' 4 | tag-template: 'next' 5 | -------------------------------------------------------------------------------- /docker/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkins-infra/docker-issue-redirect/main/docker/favicon.ico -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | -------------------------------------------------------------------------------- /Jenkinsfile_k8s: -------------------------------------------------------------------------------- 1 | buildDockerAndPublishImage('issue-redirect', [ 2 | publishToPrivateAzureRegistry: true, 3 | targetplatforms: 'linux/amd64,linux/arm64', 4 | ]) 5 | -------------------------------------------------------------------------------- /compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | build: 4 | context: . 5 | ports: 6 | - "8060:80" 7 | volumes: 8 | - "./docker/index.html:/htdocs/index.html" 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | IMAGE_NAME=$(notdir $(CURDIR))-app 2 | 3 | .PHONY: up down clean 4 | 5 | up: 6 | docker compose -f compose.yml up -d --build 7 | 8 | down: 9 | docker compose -f compose.yml down -v 10 | 11 | clean: down 12 | docker rmi $(IMAGE_NAME) || true 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bash:5.3.8-alpine3.22 AS builder 2 | 3 | WORKDIR / 4 | 5 | COPY . . 6 | RUN ./bin/redirects.sh 7 | 8 | FROM nginx:1.29.3-alpine 9 | 10 | RUN mkdir -p /etc/nginx/includes 11 | 12 | COPY --from=builder jira-to-github-redirects.conf /etc/nginx/includes/jira-to-github-redirects.conf 13 | 14 | COPY docker/favicon.ico /htdocs/favicon.ico 15 | COPY docker/default.conf /etc/nginx/conf.d/default.conf 16 | COPY docker/index.html /htdocs/index.html 17 | -------------------------------------------------------------------------------- /docker/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name _ localhost; 4 | 5 | root /htdocs; 6 | 7 | # Exact generated redirects 8 | include includes/jira-to-github-redirects.conf; 9 | 10 | # Generic fallback rewrites 11 | rewrite ^/issue/([0-9]+)$ https://issues.jenkins.io/browse/JENKINS-$1 permanent; 12 | rewrite ^/issue/([A-Z]+-[0-9]+)$ https://issues.jenkins.io/browse/$1 permanent; 13 | rewrite ^/([A-Z]+-[0-9]+)$ https://issues.jenkins.io/browse/$1 permanent; 14 | rewrite ^/browse/([A-Z]+-[0-9]+)$ https://issues.jenkins.io/browse/$1 permanent; 15 | 16 | return 404; 17 | } 18 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | on: 3 | push: 4 | workflow_dispatch: 5 | release: 6 | # Only allow 1 release-drafter build at a time to avoid creating multiple "next" releases 7 | concurrency: "release-drafter" 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Check out 13 | uses: actions/checkout@v6 14 | with: 15 | fetch-depth: 0 16 | - name: Release Drafter 17 | uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0 18 | with: 19 | name: next 20 | tag: next 21 | version: next 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2025-, Jenkins project contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-issue-redirect 2 | 3 | A simple service for redirecting issues to GitHub if they've been migrated or Jira if they haven't been. 4 | 5 | The script [redirect.sh](./bin/redirects.sh) takes a file [jira_keys_to_github_ids.txt](./mappings/jira_keys_to_github_ids.txt) and generates nginx redirect directives. 6 | 7 | A default rule will redirect any unknown issue IDs to Jira. 8 | 9 | ## API 10 | 11 | - `GET /browse/:jira_key` - Redirects to the corresponding GitHub issue, if found. Otherwise to Jira. 12 | - `GET /:jira_key` - Redirects to the corresponding GitHub issue, if found. Otherwise to Jira. (Kept for compatibility with existing uses) 13 | - `GET /issue/:jira_key_id` - Redirects to the corresponding GitHub issue, if found. Otherwise to Jira prefixing it with `JENKINS-`. (Kept for compatibility with existing uses) 14 | 15 | Ex: 16 | - `https://issue-redirect.jenkins.io/JENKINS-1` 17 | - `https://issue-redirect.jenkins.io/INFRA-1` 18 | - `https://issue-redirect.jenkins.io/issue/1` 19 | 20 | ## Adding more 21 | 22 | To add more Jira redirects send a pull request to [jira_keys_to_github_ids.txt](./mappings/jira_keys_to_github_ids.txt). 23 | 24 | To add redirections for issues of another Jira project than the ones already included, you'll also have to update [redirect.sh](./redirect.sh) 25 | -------------------------------------------------------------------------------- /bin/redirects.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | REDIRECTS_FILE="jira-to-github-redirects.conf" 6 | 7 | MAPPINGS_FILE="mappings/jira_keys_to_github_ids.txt" 8 | 9 | # Clear or create the redirects file 10 | > "$REDIRECTS_FILE" 11 | 12 | # Process each line 13 | while IFS=: read -r jira_key github_ref; do 14 | # JENKINS project 15 | if [[ $jira_key =~ JENKINS-([0-9]+) ]]; then 16 | issue_num="${BASH_REMATCH[1]}" 17 | 18 | # Extract the repo path and issue number from github_ref (e.g., jenkinsci/jenkins#13336) 19 | if [[ $github_ref =~ (.+)#([0-9]+) ]]; then 20 | repo_path="${BASH_REMATCH[1]}" 21 | github_issue="${BASH_REMATCH[2]}" 22 | 23 | { 24 | echo "rewrite ^/issue/$issue_num$ https://github.com/$repo_path/issues/$github_issue permanent;" 25 | echo "rewrite ^/issue/JENKINS-$issue_num$ https://github.com/$repo_path/issues/$github_issue permanent;" 26 | echo "rewrite ^/JENKINS-$issue_num$ https://github.com/$repo_path/issues/$github_issue permanent;" 27 | echo "rewrite ^/browse/JENKINS-$issue_num$ https://github.com/$repo_path/issues/$github_issue permanent;" 28 | } >> "$REDIRECTS_FILE" 29 | fi 30 | fi 31 | # INFRA project 32 | if [[ $jira_key =~ INFRA-([0-9]+) ]]; then 33 | issue_num="${BASH_REMATCH[1]}" 34 | 35 | # Extract the repo path and issue number from github_ref (e.g., jenkins-infra/helpdesk#83 36 | if [[ $github_ref =~ (.+)#([0-9]+) ]]; then 37 | repo_path="${BASH_REMATCH[1]}" 38 | github_issue="${BASH_REMATCH[2]}" 39 | 40 | { 41 | echo "rewrite ^/INFRA-$issue_num$ https://github.com/$repo_path/issues/$github_issue permanent;" 42 | echo "rewrite ^/issue/INFRA-$issue_num$ https://github.com/$repo_path/issues/$github_issue permanent;" 43 | echo "rewrite ^/browse/INFRA-$issue_num$ https://github.com/$repo_path/issues/$github_issue permanent;" 44 | } >> "$REDIRECTS_FILE" 45 | fi 46 | fi 47 | done < "$MAPPINGS_FILE" 48 | 49 | echo "Redirects file generated at $REDIRECTS_FILE" 50 | 51 | -------------------------------------------------------------------------------- /docker/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Issue tracker redirector 8 | 9 | 10 | 11 | 12 |
13 |

Issue tracker redirector

14 | 15 |

API:

16 | 21 | 22 |

Example of usage:

23 |

24 | From a Jira link like issues.jenkins.io/browse/JENKINS-1, replace its subdomain by issue-redirect: issue-redirect.jenkins.io/browse/JENKINS-1 25 |

26 | 27 |

To add more Jira redirects send a pull request to jira_keys_to_github_ids.txt.

28 |
29 | 30 | 31 | 32 | --------------------------------------------------------------------------------