|
1 | | -# ============================================================================ |
2 | | -# PROPOSED replacement for: Keyfactor/actions/.github/workflows/update-catalog.yml |
3 | | -# |
4 | | -# Changes from current version: |
5 | | -# 1. Adds validation gate (repo name filter, manifest field checks, visibility) |
6 | | -# 2. Replaces direct-to-main commit with PR-based flow |
7 | | -# 3. Handles private repos as "Coming Soon" entries (link_github=false) |
8 | | -# 4. Labels PRs by type: catalog-add, catalog-update, coming-soon |
9 | | -# ============================================================================ |
10 | | - |
11 | | -name: Update Keyfactor Integrations Catalog Entry |
12 | | -on: |
13 | | - workflow_call: |
14 | | - secrets: |
15 | | - token: |
16 | | - description: 'Secret token from caller workflow to access catalog repo' |
17 | | - required: true |
18 | | - |
19 | | -jobs: |
20 | | - update-catalog-entry: |
21 | | - runs-on: ubuntu-latest |
22 | | - |
23 | | - steps: |
24 | | - - name: Checkout project repo |
25 | | - uses: keyfactor/checkout@v4 |
26 | | - |
27 | | - - name: Checkout catalog repo |
28 | | - uses: keyfactor/checkout@v4 |
29 | | - with: |
30 | | - token: ${{ secrets.token }} |
31 | | - path: './catalog-temp/' |
32 | | - repository: 'Keyfactor/integrations-catalog' |
33 | | - |
34 | | - # ---------------------------------------------------------------- |
35 | | - # STEP 1: Validation Gate |
36 | | - # ---------------------------------------------------------------- |
37 | | - - name: Validate entry |
38 | | - id: validate |
39 | | - env: |
40 | | - GH_TOKEN: ${{ secrets.token }} |
41 | | - REPO_NAME: ${{ github.event.repository.name }} |
42 | | - REPO_FULL: ${{ github.repository }} |
43 | | - run: | |
44 | | - echo "### Validating: $REPO_NAME" >> "$GITHUB_STEP_SUMMARY" |
45 | | -
|
46 | | - # --- Failsafe: reject -dev, -test, -staging, -poc repo names --- |
47 | | - # NOTE: This is a failsafe only. Developers are responsible for setting |
48 | | - # update_catalog=false in their manifest for non-production repos. |
49 | | - if echo "$REPO_NAME" | grep -qE '-(dev|test|staging|poc)$'; then |
50 | | - echo "::error::Repository name '$REPO_NAME' matches a non-production pattern (-dev, -test, -staging, -poc). Set update_catalog=false in your integration-manifest.json for non-production repos." |
51 | | - echo "rejected=true" >> "$GITHUB_OUTPUT" |
52 | | - echo "reject_reason=Repo name matches non-production pattern. Developers: set \`update_catalog=false\` in your manifest." >> "$GITHUB_OUTPUT" |
53 | | - exit 1 |
54 | | - fi |
55 | | -
|
56 | | - # --- Validate required manifest fields --- |
57 | | - if [ ! -f "integration-manifest.json" ]; then |
58 | | - echo "::error::integration-manifest.json not found in repository root." |
59 | | - exit 1 |
60 | | - fi |
61 | | -
|
62 | | - NAME=$(jq -r '.name // empty' integration-manifest.json) |
63 | | - TYPE=$(jq -r '.integration_type // empty' integration-manifest.json) |
64 | | - DESC=$(jq -r '.description // empty' integration-manifest.json) |
65 | | - LINK_GITHUB=$(jq -r '.link_github // "true"' integration-manifest.json | tr '[:upper:]' '[:lower:]') |
66 | | -
|
67 | | - ERRORS="" |
68 | | - if [ -z "$NAME" ]; then |
69 | | - ERRORS="$ERRORS\n- Missing required field: \`name\`" |
70 | | - fi |
71 | | - if [ -z "$TYPE" ]; then |
72 | | - ERRORS="$ERRORS\n- Missing required field: \`integration_type\`" |
73 | | - fi |
74 | | - if [ -z "$DESC" ]; then |
75 | | - ERRORS="$ERRORS\n- Missing required field: \`description\`" |
76 | | - fi |
77 | | -
|
78 | | - # Validate integration_type against allowed values |
79 | | - ALLOWED_TYPES="orchestrator windows-orchestrator iot-orchestrator ca-gateway anyca-plugin caplugin dns-plugin pam approval-handler orchestrator-registration metadata registration-handler alert-handler api-client terraform" |
80 | | - if [ -n "$TYPE" ]; then |
81 | | - if ! echo "$ALLOWED_TYPES" | grep -qw "$TYPE"; then |
82 | | - ERRORS="$ERRORS\n- Invalid \`integration_type\`: \`$TYPE\`. Allowed: $ALLOWED_TYPES" |
83 | | - fi |
84 | | - fi |
85 | | -
|
86 | | - if [ -n "$ERRORS" ]; then |
87 | | - printf "::error::Manifest validation failed:%b\n" "$ERRORS" |
88 | | - exit 1 |
89 | | - fi |
90 | | -
|
91 | | - # --- Check repo visibility --- |
92 | | - IS_PRIVATE=$(gh api "repos/$REPO_FULL" --jq '.private') |
93 | | -
|
94 | | - if [ "$IS_PRIVATE" = "true" ] && [ "$LINK_GITHUB" = "true" ]; then |
95 | | - echo "::error::Repository '$REPO_FULL' is private but link_github=true. This would create a broken link on the public catalog. Set link_github=false in your manifest to create a 'Coming Soon' entry, or make the repo public first." |
96 | | - exit 1 |
97 | | - fi |
98 | | -
|
99 | | - # Determine entry type for labeling |
100 | | - if [ "$IS_PRIVATE" = "true" ] && [ "$LINK_GITHUB" = "false" ]; then |
101 | | - echo "entry_type=coming-soon" >> "$GITHUB_OUTPUT" |
102 | | - echo "Entry type: Coming Soon (private repo)" >> "$GITHUB_STEP_SUMMARY" |
103 | | - elif [ -f "./catalog-temp/_integrations/$REPO_NAME.md" ]; then |
104 | | - echo "entry_type=catalog-update" >> "$GITHUB_OUTPUT" |
105 | | - echo "Entry type: Update (existing entry)" >> "$GITHUB_STEP_SUMMARY" |
106 | | - else |
107 | | - echo "entry_type=catalog-add" >> "$GITHUB_OUTPUT" |
108 | | - echo "Entry type: Add (new entry)" >> "$GITHUB_STEP_SUMMARY" |
109 | | - fi |
110 | | -
|
111 | | - echo "link_github=$LINK_GITHUB" >> "$GITHUB_OUTPUT" |
112 | | - echo "Validation passed" >> "$GITHUB_STEP_SUMMARY" |
113 | | -
|
114 | | - # ---------------------------------------------------------------- |
115 | | - # STEP 2: Render Template |
116 | | - # ---------------------------------------------------------------- |
117 | | - - uses: Keyfactor/jinja2-action@v1.2.0-multiple-data-files |
118 | | - with: |
119 | | - template: ./catalog-temp/_integration.md.tpl |
120 | | - output_file: ${{ format('./catalog-temp/_integrations/{0}.md', github.event.repository.name) }} |
121 | | - data_file: integration-manifest.json |
122 | | - variables: | |
123 | | - repository= ${{ format('https://github.com/{0}', github.repository) }} |
124 | | - env: |
125 | | - GITHUB_TOKEN: ${{ secrets.token }} |
126 | | - |
127 | | - # ---------------------------------------------------------------- |
128 | | - # STEP 3: Create PR (instead of direct commit) |
129 | | - # ---------------------------------------------------------------- |
130 | | - - name: Create or update PR |
131 | | - env: |
132 | | - GH_TOKEN: ${{ secrets.token }} |
133 | | - REPO_NAME: ${{ github.event.repository.name }} |
134 | | - ENTRY_TYPE: ${{ steps.validate.outputs.entry_type }} |
135 | | - working-directory: './catalog-temp/' |
136 | | - run: | |
137 | | - BRANCH="catalog-update/$REPO_NAME" |
138 | | -
|
139 | | - git config user.name "Keyfactor" |
140 | | - git config user.email "keyfactor@keyfactor.github.io" |
141 | | -
|
142 | | - # Check if branch already exists on remote |
143 | | - if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then |
144 | | - git fetch origin "$BRANCH" |
145 | | - git checkout "$BRANCH" |
146 | | - git reset --hard origin/main |
147 | | - else |
148 | | - git checkout -b "$BRANCH" |
149 | | - fi |
150 | | -
|
151 | | - # Stage the rendered file |
152 | | - git add "_integrations/$REPO_NAME.md" --force |
153 | | -
|
154 | | - # Check if there are actual changes |
155 | | - if git diff --cached --quiet; then |
156 | | - echo "No changes detected — catalog entry is already up to date." |
157 | | - echo "### No changes" >> "$GITHUB_STEP_SUMMARY" |
158 | | - echo "Catalog entry for \`$REPO_NAME\` is already current." >> "$GITHUB_STEP_SUMMARY" |
159 | | - exit 0 |
160 | | - fi |
161 | | -
|
162 | | - # Determine commit message |
163 | | - case "$ENTRY_TYPE" in |
164 | | - catalog-add) |
165 | | - COMMIT_MSG="Add catalog entry for $REPO_NAME" |
166 | | - PR_TITLE="Add integration: $REPO_NAME" |
167 | | - ;; |
168 | | - catalog-update) |
169 | | - COMMIT_MSG="Update catalog entry for $REPO_NAME" |
170 | | - PR_TITLE="Update integration: $REPO_NAME" |
171 | | - ;; |
172 | | - coming-soon) |
173 | | - COMMIT_MSG="Add Coming Soon catalog entry for $REPO_NAME" |
174 | | - PR_TITLE="Coming Soon: $REPO_NAME" |
175 | | - ;; |
176 | | - esac |
177 | | -
|
178 | | - git commit -m "$COMMIT_MSG" |
179 | | - git push origin "$BRANCH" --force |
180 | | -
|
181 | | - # Ensure the three labels this workflow uses exist (idempotent — gh |
182 | | - # label create exits 1 if the label is already present, which we |
183 | | - # swallow). Without this, gh pr create --label hard-fails when the |
184 | | - # label is missing in the catalog repo. |
185 | | - gh label create catalog-add --color "2ECC71" --description "New integration entry added to the catalog" 2>/dev/null || true |
186 | | - gh label create catalog-update --color "1A73E8" --description "Existing integration entry updated" 2>/dev/null || true |
187 | | - gh label create coming-soon --color "F39C12" --description "Private repo published as a Coming Soon entry" 2>/dev/null || true |
188 | | -
|
189 | | - # Build PR body |
190 | | - PR_BODY=$(cat <<EOF |
191 | | - ## Catalog Entry: \`$REPO_NAME\` |
192 | | -
|
193 | | - **Type:** $ENTRY_TYPE |
194 | | - **Source:** [${REPO_NAME}](https://github.com/${{ github.repository }}) |
195 | | - **Triggered by:** Push to \`${{ github.ref_name }}\` by @${{ github.actor }} |
196 | | -
|
197 | | - ### Entry Preview |
198 | | - \`\`\`yaml |
199 | | - $(cat "_integrations/$REPO_NAME.md") |
200 | | - \`\`\` |
201 | | -
|
202 | | - --- |
203 | | - *This PR was automatically created by the catalog update workflow.* |
204 | | - *Review the entry content above and merge when ready.* |
205 | | - EOF |
206 | | - ) |
207 | | -
|
208 | | - # Check if a PR already exists for this branch |
209 | | - EXISTING_PR=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || true) |
210 | | -
|
211 | | - if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "null" ]; then |
212 | | - echo "PR #$EXISTING_PR already exists for branch $BRANCH — updated with force push." |
213 | | - echo "### Updated existing PR #$EXISTING_PR" >> "$GITHUB_STEP_SUMMARY" |
214 | | - else |
215 | | - gh pr create \ |
216 | | - --title "$PR_TITLE" \ |
217 | | - --body "$PR_BODY" \ |
218 | | - --label "$ENTRY_TYPE" \ |
219 | | - --base main \ |
220 | | - --head "$BRANCH" |
221 | | -
|
222 | | - echo "### Created PR" >> "$GITHUB_STEP_SUMMARY" |
223 | | - echo "PR created for \`$REPO_NAME\` with label \`$ENTRY_TYPE\`" >> "$GITHUB_STEP_SUMMARY" |
224 | | - fi |
| 1 | +name: Update Keyfactor Integrations Catalog Entry |
| 2 | +on: |
| 3 | + workflow_call: |
| 4 | + secrets: |
| 5 | + token: |
| 6 | + description: 'Secret token from caller workflow to access SDK repo' |
| 7 | + required: true |
| 8 | + |
| 9 | +jobs: |
| 10 | + update-catalog-entry: |
| 11 | + runs-on: ubuntu-latest |
| 12 | + |
| 13 | + steps: |
| 14 | + - name: Checkout project repo |
| 15 | + uses: keyfactor/checkout@v4 |
| 16 | + |
| 17 | + - name: Checkout catalog repo |
| 18 | + uses: keyfactor/checkout@v4 |
| 19 | + with: |
| 20 | + token: ${{ secrets.token }} |
| 21 | + path: './catalog-temp/' |
| 22 | + repository: 'Keyfactor/integrations-catalog' # Change back to integrations-catalog after testing |
| 23 | + |
| 24 | + - uses: Keyfactor/jinja2-action@v1.2.0-multiple-data-files |
| 25 | + with: |
| 26 | + template: ./catalog-temp/_integration.md.tpl |
| 27 | + output_file: ${{ format('./catalog-temp/_integrations/{0}.md', github.event.repository.name) }} |
| 28 | + data_file: integration-manifest.json |
| 29 | + variables: | |
| 30 | + repository= ${{ format('https://github.com/{0}', github.repository) }} |
| 31 | + env: |
| 32 | + GITHUB_TOKEN: ${{ secrets.token }} |
| 33 | + |
| 34 | + - uses: Keyfactor/add-and-commit@v9.1.4 |
| 35 | + with: |
| 36 | + author_name: 'Keyfactor' |
| 37 | + author_email: 'keyfactor@keyfactor.github.io' |
| 38 | + branch: 'main' |
| 39 | + message: ${{ format('Added the manifest for {0}', github.event.repository.name) }} |
| 40 | + add: ${{ format('_integrations/{0}.md --force', github.event.repository.name) }} |
| 41 | + cwd: './catalog-temp/' |
0 commit comments