
Jira Automation: en smertefri vei til automatisering, eller? đ
Du vet den fĂžlelsen nĂ„r du finner et lite hjĂžrne av arbeidsflyten som roper âdette burde gĂ„ an Ă„ automatisereâ? Ikke fordi det er kritisk, men fordi det pirrer nysgjerrigheten, det er akkurat passe komplekst til at du fĂ„r testet noe nytt, og enkelt nok til at det kanskje kan lĂžses pĂ„ en ettermiddag.
Vel, det var akkurat det som skjedde da vi bestemte oss for Ä automatisere en liten, men viktig del av rekrutteringsprosessen vÄr i SnÞkam. Uheldigvis hadde den "enkle" lÞsningen (Jira Automation) veldig mange uforutsette egenskaper som vi skal utforske litt nÄ.
Caset: Varsler om kandidater klare for kontakt
Vi Ăžnsket en automatisk oppsummering av alle kandidater vi hadde markert som âfĂžlg opp senereâ i rekrutteringslĂžpet vĂ„rt. Med andre ord kandidater vi har kontaktet fĂžr og som vi nĂ„ Ăžnsker Ă„ ta kontakt med igjen.
MÄlet var at systemet skulle:
- Finne kandidatene i Jira der status er âFĂLGE OPP SENEREâ og datoen for Ă„ fĂžlge de opp har passert.
- Flytte dem automatisk til kolonnen âKlare til Ă„ kontaktesâ.
- Sende en oppsummeringsvarsel pÄ Slack til en kanal hvor de ansvarlige for kandidatene blir tagget.
Det hÞres jo trivielt ut, ikke sant? En liten daglig pÄminnelse, midt i lunsjen, som holder alle oppdatert.
Hvorfor ikke Logic Apps eller Function Apps?
Med tidligere erfaring fra Azure Function Apps og Logic Apps falt tankene raskt dit fÞrst. Det er trygt, kjent, fleksibelt, men det betyr ogsÄ mer kode, mer infrastruktur og mer vedlikehold.
SĂ„ da jeg oppdaget at Jira Automation tilsynelatende hadde stĂžtte for Slack-integrasjon og koblinger mot Jira boards, tenkte jeg:
"Hvorfor ikke utforske noe litt annerledes?"
Hva er egentlig Jira Automation? Det er et innebygd verktÞy i Jira som lar deg automatisere oppgaver og prosesser uten kode. Det brukes ofte til Ä hÄndtere repetitive oppgaver, som Ä oppdatere statuser, redigere issues i Jira eller sende varsler, mot andre systemer som Slack, Teams eller e-post. Med enkle regler, triggere og betingelser kan du bygge smÄ arbeidsflyter som sparer tid og reduserer manuelle feil, spesielt i prosjekter med faste rutiner eller mange deltakere.
Siden Jira Automation er sÄ tett knyttet mot Jira blir dette Äpenbart mindre jobb og raskere utvikling, ikke sant?
Oppsettet i Jira Automation
Oppsettet gikk faktisk overraskende smertefritt.
Vi opprettet en Scheduled rule med en enkel CRON-jobb som kjÞrer hver dag kl. 12:00. Denne kan customises med vanlig CRON format (* * * * *). I tillegg er det mulig Ä bestemme nÄr jobben skal starte og vÊre aktiv, og potensielt datoen nÄr den skal deaktiveres, uten Ä faktisk mÄtte aktivere/deaktivere jobben, som er veldig handy.
Vi gjÞr sÄ et oppslag mot Jira med denne JQL-spÞrringen:
status = 'FĂLGE OPP SENERE' and 'start Date' <= now()
Vi har nÄ tilgang til {{lookupIssues}} som er resultatet av oppslaget med Ä bruke smart variables for Ä ta i bruk og jobbe videre med dataene.
Hvis ingen kandidater matcher oppslaget, avbrytes regelen. Her kunne vi sendt en melding til Slack med âIngen kandidater Ă„ fĂžlge opp i dagâ, men vi prĂžver Ă„ unngĂ„ stĂžy sĂ„ vi lot det vĂŠre.
Dersom det finnes kandidater gjĂžr vi fĂžlgende:
- Itererer over dem.
- Flytter dem med âTransition issueâ funksjonalitet til riktig kolonne (i dette tilfellet: "Klare til Ă„ kontaktes").
3. Til slutt Sender en Slack-melding med kandidatens navn og hvem som er Assignee.
Det fÞltes nesten for enkelt. Helt til vi stÞtte pÄ veggen aka tagging av Assignee i slack meldingen. "summary" i bildet over er navnet pÄ den aktuelle kandidaten.
Limitations â eller âderfor skriver jeg dette innleggetâ
Alt sÄ ut til Ä fungere perfekt⊠frem til jeg prÞvde Ä gjÞre det siste steget: Ä tagge de ansvarlige i Slack.
Og det er her Jira Automation viser sitt sanne jeg. Ikke fordi det ikke fungerer, men fordi det fungerer nesten. Her er de stĂžrste hindringene jeg mĂžtte:
1. Du kan ikke endre variabler. Punktum.
I Jira Automation kan du sette en variabel (og statiske tabeller), men du kan aldri endre den etterpĂ„. Ingen mutasjoner. Ingen akkumulerte verdier. Ikke engang en âmidlertidig listeâ du kan bygge underveis. Du kan lage en ny variabel basert pĂ„ en eksisterende, men du kan aldri endre originalen.
Jeg prÞvde "alt", inkludert Ä lage et dummy issue for Ä lagre informasjon midlertidig, uten hell. Vi Þnskte ikke at det kom 10 meldinger nÄr det var 10 personer som var aktuelle Ä kontakte igjen, sÄ det Ä sende ut en melding i branchen som vist over, nÄr vi flytter hvert element, var ikke aktuelt. Hvordan skal man da holde oversikt over kandidatene man flytter, uten en liste?
2. Tagging i en Slack post er ikke sÄ lett som du tror
Slack krever at du bruker bruker-ID, ikke navn eller e-post, for Ä tagge. Den finner en ved Ä gÄ inn pÄ profilen til brukeren og bruke Meatballsmenyen for Ä sÄ bruke "Copy member ID" eller tilsvarende pÄ norsk.
Planen var Ä hente denne Slack-IDen via e-posten fra Jira-brukeren, men da vi ikke har noen lett mÄter Ä lagre dette svaret pÄ har vi ikke mulighet til Ä lage en oppsummeringspost som var oppgaven. I tillegg gjÞr Jira det litt vanskelig da de gir mulighet for brukere Ä skjule e-posten sin (skjult er ogsÄ default). Informasjonen under er tatt fra dokumentasjonen til Jira relatert til Ä hente brukere:
- Jira Cloud end users can choose to hide their personal account details, including an email address from others. For more details, see the Profile visibility overview.
- To easily retrieve all users' email addresses, use the user management page (<yourcompany>.atlassian.net/admin) on the website for a straightforward export option.
Med andre ord litt tungvint, men en kunne funnet en vei rundt problemet relatert til Ä hente ut eposten til en bruker (ref: https://support.atlassian.com/jira/kb/retrieve-email-addresses-of-users-through-jira-cloud-rest-api/). Problemet er bare at Ä kunne lagre verdien til brukeren nÄr en fÄr den tilbake vil bli et stÞrre problem uansett.
3. LÞkker og oppsummeringer = dÄrlig kombo
PÄ grunn av at en ikke kan akkumlere opp data fra loops pÄ en fornuftig mÄte mÄ en enten spamme Slack med én melding per kandidat, eller sÄ mÄ du ty til kreative (og ganske hacky) lÞsninger med regex og statiske templates som vi kommer til Ä se mer pÄ senere.
4 Andre interessante egenskaper
Branch loops kjĂžrer parallelt, ikke sekvensielt. Jira gir ingen garanti for rekkefĂžlgen. Med andre ord om du forventer sekvensiell logikk kan du glemme det.
NÄr en itererer over en smart value (med Ä bruke {{#lookupIssues}}... {{/}}{{/lookupIssues}} notasjon) vil alle verdier utenfor scopet vÊre utilgjengelige. Dette betyr at i vÄrt tilfelle nÄr vi skal sende Slack-posten har vi ikke tilgang til andre ting en verdiene fra lookupIssues som gjÞr det vanskelig Ä lage en fin melding uten duplikat informasjon.
LĂžsningen
I stedet for Ă„ gi opp (eller skrive en Function/Logic App som jeg kanskje burde gjort), valgte vi en enklere, men litt mer manuell lĂžsning.
Statisk ID-tabell:
Vi lagde en enkel key-value-oversikt der nĂžkkelen er Jira-brukerens ID og verdien er Slack-IDen.
NÄr noen nye blir med pÄ rekrutteringsteamet, oppdateres tabellen manuelt. Ulempen? Ja, litt manuelt arbeid.
Fordelen? Det fungerer, og vi fÄr beskjed i Slack nÄr noen ikke blir tagget, sÄ det er lett Ä fikse eventuelle mangler.
Regex-magi:
For Ä hente riktig bruker fra den statiske listen mÄtte vi bruke litt regex-magi, heldigvis med god hjelp fra flere Jira community poster. NÄr vi sÄ lager en variabel med regexen vil vi faktisk kunne bruke den variabelen utenfor loopen i Slack posten som vi sÄ over, og unngÄr da den begrensningen.
FÞrst mÄ vi gjÞre den statiske id tabellen vÄr mer sÞkbare sÄ vi gjÞr den om til ren tekst pÄ fÞlgende format: jiraId1~slackId1;jiraId2~slackId2;
idTableAsString = {{#ids.entries}}{{key}}~{{value}};{{/}}
Deretter mÄ vi lage en Regex expression ut av hvilke personer vi Þnsker Ä tagge slik at vi kan matche disse med den sÞkbare teksten vi lagde over. Regexen under blir fÞlgende: jiraId1~.*|jiraId2~.* hvor jiraId1~ er for Ä matche jiraIden i den statiske tabellen, .* er for Ä finne resten av teksten, med andre ord slackId, og | for Ä matche jiraId1 eller jiraId2 osv.
jiraIdsMatchRegex = ({{#lookupIssues.assignee.accountId}}{{.}}~.*{{^last}}|{{/}}{{/}})
Til slutt skal vi gjĂžre selve matchingen:
- Vi splitter den sÞkbare idteksten vÄr i hver key value pair
- Matcher de med regexen
- Tar den siste delen av hver key value pair, med andre ord slackIden
- FÞr vi assigner den pÄ fÞlgende format: <@slackId1>,<@slackId2> som er mÄten en tagger personer nÄr en poster mot slack.
allAssigneeToTag = {{#idTableAsString.split(";").match(jiraIdsMatchRegex).substringAfter("~")}} <@{{.}}>,{{/}}
Duplicates everywhere
I stedet for Ä fÄ en fine liste med Kandidat - @Ansvarlig blir det nÄ bare tekst og selve taggingen kommer som en liste pÄ slutten. Egentlig skulle jeg Þnske det var mulig Ä gjÞre det inline i selve Slack actionen, men en har ikke tilgang til out-of-scope variabler nÄr en itererer over en smart value som {{lookupIssues}}. Derfor mÄ vi dessverre legge en duplikatliste med pÄ bunnen med tags. Resultatet:
Lesson learned
Til syvende og sist lĂŠrte jeg mer av denne lille automasjonsĂžvelsen enn jeg forventet.
Ikke fordi Jira Automation lÞste alt for meg, men fordi begrensningene tvang frem en forstÄelse av hvor verktÞyet skinner, og hvor det ikke bÞr presses lenger enn nÞdvendig.
Jira Automation er et glimrende verktÞy nÄr du:
- vil automatisere smÄ, repeterende prosesser,
- opererer med tydelige og enkle regler,
- ikke trenger avansert tilstandsÂhĂ„ndtering,
- og Ăžnsker rask gevinst uten infrastruktur.
Men nÄr du:
- trenger databehandling over flere steg,
- mÄ matche eksterne systemer som ikke deler ID-format,
- vil bygge konsistente integrasjoner,
da er det pĂ„ tide Ă„ ta frem bedre verktĂžy, som Function Apps eller Logic Apps â og la Jira Automation gjĂžre det det er best til:
enkel, effektiv automasjon innenfor Jira sitt univers.
Resultatet er ihvertfall at vi nĂ„ har en automatisk prosess for Ă„ minne oss selv og hverandre pĂ„ Ă„ holde kontakt med kandidater som Ăžnsker inn i SnĂžkamâĄ