ARROW-11203: [Developer][Website] Enable JIRA and pull request integration

This is borrowed from
https://github.com/apache/arrow/tree/master/.github/workflows .

Closes #88 from kou/developer-pr-jira-integration and squashes the following commits:

88b3cfcc7 <Sutou Kouhei>  Enable JIRA and pull request integration

Authored-by: Sutou Kouhei <kou@clear-code.com>
Signed-off-by: Sutou Kouhei <kou@clear-code.com>
diff --git a/.github/workflows/dev_pr.yml b/.github/workflows/dev_pr.yml
new file mode 100644
index 0000000..fbcb20c
--- /dev/null
+++ b/.github/workflows/dev_pr.yml
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Dev PR
+
+on:
+  pull_request_target:
+    types:
+      - opened
+      - edited
+
+jobs:
+  process:
+    name: Process
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Comment JIRA link
+        uses: actions/github-script@v3
+        with:
+          github-token: ${{ secrets.GITHUB_TOKEN }}
+          script: |
+            const script = require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/dev_pr/link.js`);
+            script({github, context});
+
+      - name: Check title
+        uses: actions/github-script@v3
+        with:
+          github-token: ${{ secrets.GITHUB_TOKEN }}
+          script: |
+            const script = require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/dev_pr/title_check.js`);
+            script({github, context});
diff --git a/.github/workflows/dev_pr/link.js b/.github/workflows/dev_pr/link.js
new file mode 100644
index 0000000..550a9cd
--- /dev/null
+++ b/.github/workflows/dev_pr/link.js
@@ -0,0 +1,69 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+function detectJIRAID(title) {
+  if (!title) {
+    return null;
+  }
+  const matched = /^(WIP:?\s*)?((ARROW|PARQUET)-\d+)/.exec(title);
+  if (!matched) {
+    return null;
+  }
+  return matched[2];
+}
+
+async function haveComment(github, context, pullRequestNumber, body) {
+  const options = {
+    owner: context.repo.owner,
+    repo: context.repo.repo,
+    issue_number: pullRequestNumber,
+    page: 1
+  };
+  while (true) {
+    const response = await github.issues.listComments(options);
+    if (response.data.some(comment => comment.body === body)) {
+      return true;
+    }
+    if (!/;\s*rel="next"/.test(response.headers.link || "")) {
+      break;
+    }
+    options.page++;
+  }
+  return false;
+}
+
+async function commentJIRAURL(github, context, pullRequestNumber, jiraID) {
+  const jiraURL = `https://issues.apache.org/jira/browse/${jiraID}`;
+  if (await haveComment(github, context, pullRequestNumber, jiraURL)) {
+    return;
+  }
+  await github.issues.createComment({
+    owner: context.repo.owner,
+    repo: context.repo.repo,
+    issue_number: pullRequestNumber,
+    body: jiraURL
+  });
+}
+
+module.exports = async ({github, context}) => {
+  const pullRequestNumber = context.payload.number;
+  const title = context.payload.pull_request.title;
+  const jiraID = detectJIRAID(title);
+  if (jiraID) {
+    await commentJIRAURL(github, context, pullRequestNumber, jiraID);
+  }
+};
diff --git a/.github/workflows/dev_pr/title_check.js b/.github/workflows/dev_pr/title_check.js
new file mode 100644
index 0000000..2a8d654
--- /dev/null
+++ b/.github/workflows/dev_pr/title_check.js
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+const fs = require("fs");
+
+function haveJIRAID(title) {
+  if (!title) {
+    return false;
+  }
+  return /^(WIP:?\s*)?(ARROW|PARQUET)-\d+/.test(title);
+}
+
+async function commentOpenJIRAIssue(github, context, pullRequestNumber) {
+  const {data: comments} = await github.issues.listComments({
+    owner: context.repo.owner,
+    repo: context.repo.repo,
+    issue_number: pullRequestNumber,
+    per_page: 1
+  });
+  if (comments.length > 0) {
+    return;
+  }
+  const commentPath = ".github/workflows/dev_pr/title_check.md";
+  const comment = fs.readFileSync(commentPath).toString();
+  await github.issues.createComment({
+    owner: context.repo.owner,
+    repo: context.repo.repo,
+    issue_number: pullRequestNumber,
+    body: comment
+  });
+}
+
+module.exports = async ({github, context}) => {
+  const pullRequestNumber = context.payload.number;
+  const title = context.payload.pull_request.title;
+  if (!haveJIRAID(title)) {
+    await commentOpenJIRAIssue(github, context, pullRequestNumber);
+  }
+};
diff --git a/.github/workflows/dev_pr/title_check.md b/.github/workflows/dev_pr/title_check.md
new file mode 100644
index 0000000..cdc7f60
--- /dev/null
+++ b/.github/workflows/dev_pr/title_check.md
@@ -0,0 +1,32 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+Thanks for opening a pull request!
+
+Could you open an issue for this pull request on JIRA?
+https://issues.apache.org/jira/browse/ARROW
+
+Then could you also rename pull request title in the following format?
+
+    ARROW-${JIRA_ID}: [${COMPONENT}] ${SUMMARY}
+
+See also:
+
+  * [Other pull requests](https://github.com/apache/arrow-site/pulls/)
+  * [Contribution Guidelines - How to contribute patches](https://arrow.apache.org/docs/developers/contributing.html#how-to-contribute-patches)