@@ -12,65 +12,128 @@ pool:
1212 docker-new
1313
1414variables :
15- - group : pipeline
15+ - group : ado-gh-sync-vg # contains GITHUB_APP_ID and GITHUB_APP_INSTALLATION_ID
1616
1717jobs :
1818- job : GitHubSync
1919 container : node18
2020 steps :
2121 - checkout : self
2222
23+ - task : DownloadSecureFile@1
24+ name : githubAppKey
25+ inputs :
26+ secureFile : ' ado-gh-sync.pem'
27+
2328 - script : |
24- if [ "$(Build.SourceBranch)" != "refs/tags/*" ]; then
25-
26- echo "This is a tag push. Sync starting..."
27- BRANCH_NAME=main
28-
29- git config --global user.email "jigar.dafda@gmail.com"
30- git config --global user.name "Jigar Dafda"
31-
32- git clone https://$(GITHUB_USERNAME):$(GITHUB_PERSONAL_TOKEN)@github.com/gofynd/fdk-store-gql.git
33- cd fdk-store-gql
34- git checkout $BRANCH_NAME
35- rm -rf ./*
36- cd ..
37-
38- cp -R `ls | grep -v "fdk-store-gql"` ./fdk-store-gql
39- cp .gitignore.ci ./fdk-store-gql/.gitignore
40-
41- cd fdk-store-gql
42- NODE_ENV=development npm i
43- npm run build
44-
45- git add .
46- git commit -m "[Auto Generated]"
47- git push origin $BRANCH_NAME
48-
49- git tag $(Build.SourceBranchName)
50- git push origin $(Build.SourceBranchName)
51-
52- # Create GitHub release
53- RELEASE_TITLE="Release_$(Build.SourceBranchName)"
54- echo $(Build.SourceBranchName)
55- echo $RELEASE_TITLE
56- echo $BRANCH_NAME
57- POST_DATA=$(printf '{
58- "tag_name": "%s",
59- "target_commitish": "%s",
60- "name": "%s",
61- "body": "%s",
62- "draft": false,
63- "prerelease": false
64- }' $(Build.SourceBranchName) $BRANCH_NAME $RELEASE_TITLE "$RELEASE_TITLE")
65- echo $POST_DATA
66- curl -X POST -H "Authorization: token $(GITHUB_PERSONAL_TOKEN)" \
67- -H "Content-Type: application/json" \
68- -d "$POST_DATA" \
69- "https://api.github.com/repos/gofynd/fdk-store-gql/releases"
70-
71-
72- else
73- echo "This is not a tag push. Exiting..."
74- exit 0
29+ set -euo pipefail
30+
31+ echo "Tag build: $(Build.SourceBranchName)"
32+ BRANCH_NAME=main
33+
34+ git config --global user.email "jigar.dafda@gmail.com"
35+ git config --global user.name "Jigar Dafda"
36+
37+ # ---- Generate GitHub App JWT (RS256) ----
38+ export GITHUB_APP_PEM_PATH="$(githubAppKey.secureFilePath)"
39+
40+ node <<'NODE'
41+ const fs = require('fs');
42+ const crypto = require('crypto');
43+
44+ function b64url(input) {
45+ return Buffer.from(input).toString('base64')
46+ .replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
47+ }
48+
49+ const appId = process.env.GITHUB_APP_ID;
50+ const pemPath = process.env.GITHUB_APP_PEM_PATH;
51+
52+ if (!appId || !pemPath) {
53+ console.error("Missing env: GITHUB_APP_ID / GITHUB_APP_PEM_PATH");
54+ process.exit(1);
55+ }
56+
57+ const privateKey = fs.readFileSync(pemPath, 'utf8');
58+
59+ const now = Math.floor(Date.now() / 1000);
60+ const header = { alg: "RS256", typ: "JWT" };
61+ const payload = {
62+ iat: now - 30,
63+ exp: now + 9 * 60, // <= 10 minutes
64+ iss: appId
65+ };
66+
67+ const unsigned = `${b64url(JSON.stringify(header))}.${b64url(JSON.stringify(payload))}`;
68+ const sign = crypto.createSign('RSA-SHA256');
69+ sign.update(unsigned);
70+ const signature = sign.sign(privateKey);
71+ const jwt = `${unsigned}.${b64url(signature)}`;
72+
73+ fs.writeFileSync('github_app_jwt.txt', jwt);
74+ NODE
75+
76+ JWT="$(cat github_app_jwt.txt)"
77+
78+ # ---- Exchange JWT for Installation Access Token ----
79+ INSTALL_TOKEN="$(
80+ curl -sS -X POST \
81+ -H "Authorization: Bearer ${JWT}" \
82+ -H "Accept: application/vnd.github+json" \
83+ "https://api.github.com/app/installations/${GITHUB_APP_INSTALLATION_ID}/access_tokens" \
84+ | node -pe "JSON.parse(require('fs').readFileSync(0,'utf8')).token"
85+ )"
86+
87+ if [ -z "$INSTALL_TOKEN" ] || [ "$INSTALL_TOKEN" = "undefined" ]; then
88+ echo "Failed to get installation token"
89+ exit 1
7590 fi
76- displayName: 'Sync with GitHub'
91+
92+ # Build header for git HTTPS auth with GitHub App token
93+ BASIC_B64="$(printf '%s:%s' "x-access-token" "$INSTALL_TOKEN" | base64 | tr -d '\n')"
94+ AUTH_HEADER="Authorization: Basic ${BASIC_B64}"
95+
96+ # ---- Sync flow ----
97+ git -c http.extraheader="$AUTH_HEADER" clone https://github.com/gofynd/fdk-store-gql.git
98+ cd fdk-store-gql
99+ git checkout "$BRANCH_NAME"
100+
101+ rm -rf ./*
102+ cd ..
103+
104+ cp -R $(ls | grep -v "fdk-store-gql") ./fdk-store-gql
105+ cp .gitignore.ci ./fdk-store-gql/.gitignore
106+
107+ cd fdk-store-gql
108+ NODE_ENV=development npm install
109+ npm run build
110+
111+ git add -A
112+ git commit -m "[Auto Generated]" || echo "No changes to commit"
113+
114+ git -c http.extraheader="$AUTH_HEADER" push origin "$BRANCH_NAME"
115+
116+ git tag "$(Build.SourceBranchName)" || echo "Tag already exists locally"
117+ git -c http.extraheader="$AUTH_HEADER" push origin "$(Build.SourceBranchName)"
118+
119+ # Create GitHub release using installation token
120+ RELEASE_TITLE="Release_$(Build.SourceBranchName)"
121+ POST_DATA=$(printf '{
122+ "tag_name": "%s",
123+ "target_commitish": "%s",
124+ "name": "%s",
125+ "body": "%s",
126+ "draft": false,
127+ "prerelease": false
128+ }' "$(Build.SourceBranchName)" "$BRANCH_NAME" "$RELEASE_TITLE" "$RELEASE_TITLE")
129+
130+ curl -sS -X POST \
131+ -H "Authorization: token ${INSTALL_TOKEN}" \
132+ -H "Accept: application/vnd.github+json" \
133+ -H "Content-Type: application/json" \
134+ -d "$POST_DATA" \
135+ "https://api.github.com/repos/gofynd/fdk-store-gql/releases"
136+ displayName: 'Sync with GitHub (GitHub App auth)'
137+ env:
138+ GITHUB_APP_ID: $(GITHUB_APP_ID)
139+ GITHUB_APP_INSTALLATION_ID: $(GITHUB_APP_INSTALLATION_ID)
0 commit comments