ha-inlite

Home Assistant integration for in-lite
git clone https://git.stephank.nl/ha-inlite
Log | Files | Refs | README | LICENSE | ZIP

squad-label-enforce.yml (7032B)


      1 name: Squad Label Enforce
      2 
      3 on:
      4   issues:
      5     types: [labeled]
      6 
      7 permissions:
      8   issues: write
      9   contents: read
     10 
     11 jobs:
     12   enforce:
     13     runs-on: ubuntu-latest
     14     steps:
     15       - uses: actions/checkout@v4
     16 
     17       - name: Enforce mutual exclusivity
     18         uses: actions/github-script@v7
     19         with:
     20           script: |
     21             const issue = context.payload.issue;
     22             const appliedLabel = context.payload.label.name;
     23 
     24             // Namespaces with mutual exclusivity rules
     25             const EXCLUSIVE_PREFIXES = ['go:', 'release:', 'type:', 'priority:'];
     26 
     27             // Skip if not a managed namespace label
     28             if (!EXCLUSIVE_PREFIXES.some(p => appliedLabel.startsWith(p))) {
     29               core.info(`Label ${appliedLabel} is not in a managed namespace — skipping`);
     30               return;
     31             }
     32 
     33             const allLabels = issue.labels.map(l => l.name);
     34 
     35             // Handle go: namespace (mutual exclusivity)
     36             if (appliedLabel.startsWith('go:')) {
     37               const otherGoLabels = allLabels.filter(l => 
     38                 l.startsWith('go:') && l !== appliedLabel
     39               );
     40 
     41               if (otherGoLabels.length > 0) {
     42                 // Remove conflicting go: labels
     43                 for (const label of otherGoLabels) {
     44                   await github.rest.issues.removeLabel({
     45                     owner: context.repo.owner,
     46                     repo: context.repo.repo,
     47                     issue_number: issue.number,
     48                     name: label
     49                   });
     50                   core.info(`Removed conflicting label: ${label}`);
     51                 }
     52 
     53                 // Post update comment
     54                 await github.rest.issues.createComment({
     55                   owner: context.repo.owner,
     56                   repo: context.repo.repo,
     57                   issue_number: issue.number,
     58                   body: `🏷️ Triage verdict updated → \`${appliedLabel}\``
     59                 });
     60               }
     61 
     62               // Auto-apply release:backlog if go:yes and no release target
     63               if (appliedLabel === 'go:yes') {
     64                 const hasReleaseLabel = allLabels.some(l => l.startsWith('release:'));
     65                 if (!hasReleaseLabel) {
     66                   await github.rest.issues.addLabels({
     67                     owner: context.repo.owner,
     68                     repo: context.repo.repo,
     69                     issue_number: issue.number,
     70                     labels: ['release:backlog']
     71                   });
     72 
     73                   await github.rest.issues.createComment({
     74                     owner: context.repo.owner,
     75                     repo: context.repo.repo,
     76                     issue_number: issue.number,
     77                     body: `📋 Marked as \`release:backlog\` — assign a release target when ready.`
     78                   });
     79 
     80                   core.info('Applied release:backlog for go:yes issue');
     81                 }
     82               }
     83 
     84               // Remove release: labels if go:no
     85               if (appliedLabel === 'go:no') {
     86                 const releaseLabels = allLabels.filter(l => l.startsWith('release:'));
     87                 if (releaseLabels.length > 0) {
     88                   for (const label of releaseLabels) {
     89                     await github.rest.issues.removeLabel({
     90                       owner: context.repo.owner,
     91                       repo: context.repo.repo,
     92                       issue_number: issue.number,
     93                       name: label
     94                     });
     95                     core.info(`Removed release label from go:no issue: ${label}`);
     96                   }
     97                 }
     98               }
     99             }
    100 
    101             // Handle release: namespace (mutual exclusivity)
    102             if (appliedLabel.startsWith('release:')) {
    103               const otherReleaseLabels = allLabels.filter(l => 
    104                 l.startsWith('release:') && l !== appliedLabel
    105               );
    106 
    107               if (otherReleaseLabels.length > 0) {
    108                 // Remove conflicting release: labels
    109                 for (const label of otherReleaseLabels) {
    110                   await github.rest.issues.removeLabel({
    111                     owner: context.repo.owner,
    112                     repo: context.repo.repo,
    113                     issue_number: issue.number,
    114                     name: label
    115                   });
    116                   core.info(`Removed conflicting label: ${label}`);
    117                 }
    118 
    119                 // Post update comment
    120                 await github.rest.issues.createComment({
    121                   owner: context.repo.owner,
    122                   repo: context.repo.repo,
    123                   issue_number: issue.number,
    124                   body: `🏷️ Release target updated → \`${appliedLabel}\``
    125                 });
    126               }
    127             }
    128 
    129             // Handle type: namespace (mutual exclusivity)
    130             if (appliedLabel.startsWith('type:')) {
    131               const otherTypeLabels = allLabels.filter(l => 
    132                 l.startsWith('type:') && l !== appliedLabel
    133               );
    134 
    135               if (otherTypeLabels.length > 0) {
    136                 for (const label of otherTypeLabels) {
    137                   await github.rest.issues.removeLabel({
    138                     owner: context.repo.owner,
    139                     repo: context.repo.repo,
    140                     issue_number: issue.number,
    141                     name: label
    142                   });
    143                   core.info(`Removed conflicting label: ${label}`);
    144                 }
    145 
    146                 await github.rest.issues.createComment({
    147                   owner: context.repo.owner,
    148                   repo: context.repo.repo,
    149                   issue_number: issue.number,
    150                   body: `🏷️ Issue type updated → \`${appliedLabel}\``
    151                 });
    152               }
    153             }
    154 
    155             // Handle priority: namespace (mutual exclusivity)
    156             if (appliedLabel.startsWith('priority:')) {
    157               const otherPriorityLabels = allLabels.filter(l => 
    158                 l.startsWith('priority:') && l !== appliedLabel
    159               );
    160 
    161               if (otherPriorityLabels.length > 0) {
    162                 for (const label of otherPriorityLabels) {
    163                   await github.rest.issues.removeLabel({
    164                     owner: context.repo.owner,
    165                     repo: context.repo.repo,
    166                     issue_number: issue.number,
    167                     name: label
    168                   });
    169                   core.info(`Removed conflicting label: ${label}`);
    170                 }
    171 
    172                 await github.rest.issues.createComment({
    173                   owner: context.repo.owner,
    174                   repo: context.repo.repo,
    175                   issue_number: issue.number,
    176                   body: `🏷️ Priority updated → \`${appliedLabel}\``
    177                 });
    178               }
    179             }
    180 
    181             core.info(`Label enforcement complete for ${appliedLabel}`);