1+ name : Mirror hiring issues to private repo and delete public copy
2+
3+ on :
4+ issues :
5+ types : [opened]
6+
7+ permissions :
8+ contents : read
9+ issues : write
10+
11+ jobs :
12+ mirror-and-delete :
13+ # Only act on issues marked as hiring/candidate
14+ if : |
15+ contains(join(github.event.issue.labels.*.name, ','), 'hiring') ||
16+ contains(join(github.event.issue.labels.*.name, ','), 'candidate')
17+ runs-on : ubuntu-latest
18+
19+ steps :
20+ - name : Install jq
21+ run : sudo apt-get update && sudo apt-get install -y jq
22+
23+ - name : Mirror to private repo and delete public issue
24+ env :
25+ GH_TOKEN : ${{ secrets.HIRING_REPO_TOKEN }}
26+
27+ SOURCE_OWNER : platformbuilds
28+ SOURCE_REPO : platformbuilds.github.io
29+
30+ TARGET_OWNER : platformbuilds
31+ TARGET_REPO : hiring
32+
33+ ISSUE_NUMBER : ${{ github.event.issue.number }}
34+ run : |
35+ set -euo pipefail
36+
37+ echo "Fetching source issue #${ISSUE_NUMBER}…"
38+
39+ issue_json=$(curl -sSL \
40+ -H "Authorization: Bearer ${GH_TOKEN}" \
41+ -H "Accept: application/vnd.github+json" \
42+ "https://api.github.com/repos/${SOURCE_OWNER}/${SOURCE_REPO}/issues/${ISSUE_NUMBER}")
43+
44+ title=$(echo "$issue_json" | jq -r '.title')
45+ body=$(echo "$issue_json" | jq -r '.body')
46+ author=$(echo "$issue_json" | jq -r '.user.login')
47+ node_id=$(echo "$issue_json" | jq -r '.node_id')
48+
49+ echo "Source title: $title"
50+ echo "Source author: $author"
51+ echo "Source node_id: $node_id"
52+
53+ private_body=$(cat <<EOF
54+ Application submitted via website → public intake issue → mirrored by GitHub Actions.
55+
56+ **Original author:** @${author}
57+ **Original issue (now deleted):** https://github.com/${SOURCE_OWNER}/${SOURCE_REPO}/issues/${ISSUE_NUMBER}
58+
59+ ---
60+
61+ ${body}
62+ EOF
63+ )
64+
65+ create_payload=$(jq -n \
66+ --arg title "$title" \
67+ --arg body "$private_body" \
68+ ' {
69+ title: $title,
70+ body: $body,
71+ labels: ["candidate", "source:public-intake"]
72+ }' )
73+
74+ echo "Creating issue in ${TARGET_OWNER}/${TARGET_REPO}…"
75+
76+ create_resp=$(curl -sSL \
77+ -X POST \
78+ -H "Authorization : Bearer ${GH_TOKEN}" \
79+ -H "Accept : application/vnd.github+json" \
80+ " https://api.github.com/repos/${TARGET_OWNER}/${TARGET_REPO}/issues" \
81+ -d "$create_payload")
82+
83+ private_issue_url=$(echo "$create_resp" | jq -r '.html_url')
84+ echo "Private issue created at : $private_issue_url"
85+
86+ # Optional scrub+close before deletion (defence in depth)
87+ scrubbed_body="Thanks for applying! Your application has been recorded in our internal hiring tracker."
88+
89+ update_payload=$(jq -n \
90+ --arg body "$scrubbed_body" \
91+ ' {
92+ body: $body,
93+ state: "closed"
94+ }' )
95+
96+ echo "Scrubbing and closing source issue before deletion…"
97+
98+ curl -sSL \
99+ -X PATCH \
100+ -H "Authorization : Bearer ${GH_TOKEN}" \
101+ -H "Accept : application/vnd.github+json" \
102+ " https://api.github.com/repos/${SOURCE_OWNER}/${SOURCE_REPO}/issues/${ISSUE_NUMBER}" \
103+ -d "$update_payload"
104+
105+ # Delete via GraphQL
106+ echo "Deleting source issue via GraphQL…"
107+
108+ graphql_query=$(jq -n \
109+ --arg id "$node_id" \
110+ ' { query: "mutation DeleteIssue($id:ID!){ deleteIssue(input:{issueId:$id}){ clientMutationId }}", variables: { id: $id } }' )
111+
112+ delete_resp=$(curl -sSL \
113+ -X POST \
114+ -H "Authorization : Bearer ${GH_TOKEN}" \
115+ -H "Accept : application/vnd.github+json" \
116+ https://api.github.com/graphql \
117+ -d "$graphql_query")
118+
119+ echo "Delete response:"
120+ echo "$delete_resp"
121+
122+ echo "Done : mirrored to private and deleted public issue."
0 commit comments