0 Seguidores · 18 Postagens

Git é um sistema de controle de versão para rastrear alterações em arquivos de computador e coordenar o trabalho nesses arquivos entre várias pessoas.

Site oficial.

Artigo Heloisa Paiva · Set. 29, 2025 2m read

Olá,

Pensei em compartilhar um hook bem útil que me ajudou no desenvolvimento no Health Connect Cloud com VS Code e GitBash. Ao desenvolver no Health Connect Cloud, se forem feitas alterações diretamente no servidor, como regras de roteamento (routing rules) ou implantações de componentes, elas não são incluídas automaticamente no controle de origem (source control). Por isso, você deve exportar do servidor para seus arquivos locais e enviar para o seu repositório remoto. Tenho certeza de que existem métodos mais fáceis para lidar com isso, os quais estou testando, mas como uma solução rápida, achei que seria útil ter um gancho de pré-commit que aciona um lembrete no GitBash - veja abaixo.

0
0 21
Artigo Heloisa Paiva · Abr. 20, 2025 6m read

Sei que pessoas completamente novas no VS Code, Git, Docker, FHIR e outras ferramentas podem, às vezes, ter dificuldades com a configuração do ambiente. Por isso, decidi escrever um artigo que percorre todo o processo de configuração passo a passo para facilitar o início.

Eu realmente agradeceria se você pudesse deixar um comentário no final – me diga se as instruções foram claras, se algo ficou faltando ou se há mais alguma coisa que você acharia útil.

A configuração inclui:

✅ VS Code – Editor de código
✅ Git – Sistema de controle de versão
✅ Docker – Executa uma instância do IRIS for Health Community
Extensão REST Client do VS Code – Para executar consultas à API FHIR
✅ Python – Para escrever scripts baseados em FHIR
✅ Jupyter Notebooks –Para tarefas de IA e FHIR

Antes de começar: Certifique-se de ter privilégios de administrador no seu sistema.

Além de ler o guia, você também pode seguir os passos nos vídeos:

Para Windows

0
0 39
InterSystems Oficial Danusa Calixto · jan 28, 2025

Já faz um tempo que não posto sobre o Embedded Git na Comunidade de Desenvolvedores, e gostaria de fornecer uma atualização sobre a enorme quantidade de trabalho que fizemos este ano e para onde estamos indo a seguir.

Contexto

Se você estiver construindo soluções no IRIS e quiser usar o Git, isso é ótimo! Basta usar o VSCode com um repositório git local e enviar suas alterações para o servidor - é muito fácil.

Mas e se:

0
0 32
Artigo Heloisa Paiva · Out. 24, 2024 7m read

fastapi_logo

Descrição

Este é um modelo para um aplicativo FastAPI que pode ser implantado no IRIS como um aplicativo Web nativo.

Instalação

  1. Clone o repositório
  2. Crie um ambiente virtual
  3. Instale os requisitos
  4. Execute o arquivo docker-compose
git clone
cd iris-fastapi-template
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
docker-compose up

Uso

A URL base é http://localhost:53795/fastapi/.

Endpoints

  • /iris - Retorna um objeto JSON com as 10 principais classes presentes no namespace IRISAPP.
  • /interop - Um endpoint de ping para testar a estrutura de interoperabilidade do IRIS.
  • /posts - Um endpoint CRUD simples para um objeto Post.
  • /comments - Um endpoint CRUD simples para um objeto Comentário.

Como desenvolver a partir deste template

Veja o artigo de introdução ao WSGI: wsgi-introduction.

TL;DR: Você pode ativar ou desativar o sinalizador DEBUG no portal de segurança para que as alterações sejam refletidas no aplicativo à medida que você desenvolve.

Apresentação do código

app.py

Este é o arquivo principal do aplicativo FastAPI. Ele contém o aplicativo FastAPI e as rotas.

from fastapi import FastAPI, Request

import iris

from grongier.pex import Director

# import models
from models import Post, Comment, init_db
from sqlmodel import Session,select

app = FastAPI()

# create a database engine
url = "iris+emb://IRISAPP"
engine = init_db(url)
  • from fastapi import FastAPI, Request - Importe a classe FastAPI e a classe Request
  • import iris - Importe o módulo IRIS.
  • from grongier.pex import Director: Importe a classe Director para vincular o aplicativo Flask ao framework de interoperabilidade do IRIS.
  • from models import Post, Comment, init_db - Importe os modelos e a função init_db.
  • from sqlmodel import Session,select - Importe a classe Session e a função select do módulo sqlmodel.
  • app = FastAPI() - Crie um aplicativo FastAPI.
  • url = "iris+emb://IRISAPP" -Defina o URL do namespace IRIS.
  • engine = init_db(url) - Crie um mecanismo de banco de dados para o ORM sqlmodel..

models.py

Este arquivo contém os modelos para o aplicativo.

from sqlmodel import Field, SQLModel, Relationship, create_engine

class Comment(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    post_id: int = Field(foreign_key="post.id")
    content: str
    post: "Post" = Relationship(back_populates="comments")

class Post(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    title: str
    content: str
    comments: list["Comment"] = Relationship(back_populates="post")

Não há muito a dizer aqui, apenas a definição dos modelos com chaves estrangeiras e relacionamentos.

A função init_db é usada para criar o mecanismo de banco de dados.

def init_db(url):

    engine = create_engine(url)

    # create the tables
    SQLModel.metadata.drop_all(engine)
    SQLModel.metadata.create_all(engine)

    # initialize database with fake data
    from sqlmodel import Session

    with Session(engine) as session:
        # Create fake data
        post1 = Post(title='Post The First', content='Content for the first post')
        ...
        session.add(post1)
        ...
        session.commit()

    return engine
  • engine = create_engine(url) - Crie um mecanismo de banco de dados.
  • SQLModel.metadata.drop_all(engine) - Exclua todas as tabelas.
  • SQLModel.metadata.create_all(engine) - Crie todas as tabelas.
  • with Session(engine) as session: - Crie uma sessão para interagir com o banco de dados.
  • post1 = Post(title='Post The First', content='Content for the first post')- Crie um objeto Post..
  • session.add(post1) -Adicione o objeto Post à sessão.
  • session.commit() -Confirme as alterações no banco de dados.
  • return engine - Retorne o mecanismo de banco de dados.

/iris endpoint

######################
# IRIS Query exemplo #
######################

@app.get("/iris")
def iris_query():
    query = "SELECT top 10 * FROM %Dictionary.ClassDefinition"
    rs = iris.sql.exec(query)
    # Convert the result to a list of dictionaries
    result = []
    for row in rs:
        result.append(row)
    return result
  • @app.get("/iris") - Defina uma rota GET para o endpoint /iris .
  • query = "SELECT top 10 * FROM %Dictionary.ClassDefinition" -Defina a consulta para obter as 10 principais classes no namespace IRIS.
  • rs = iris.sql.exec(query) - Execute a consulta..
  • result = [] - Crie uma lista vazia para armazenar os resultados.
  • for row in rs: - Itere sobre o conjunto de resultados.
  • result.append(row) - Adicione a linha à lista de resultados.
  • return result - Retorne a lista de resultados.

/interop endpoint

########################
# IRIS interop exemplo #
########################
bs = Director.create_python_business_service('BS')

@app.get("/interop")
@app.post("/interop")
@app.put("/interop")
@app.delete("/interop")
def interop(request: Request):
    
    rsp = bs.on_process_input(request)

    return rsp

  • bs = Director.create_python_business_service('BS') - Crie um business service Python. -Deve ser criado fora da definição da rota para evitar múltiplas instâncias do serviço de negócios.
  • @app.get("/interop") - Define uma rota GET para o endpoint /interop.
  • @app.post("/interop") - Define uma rota POST para o endpoin /interop .
  • ...
  • def interop(request: Request): - Define o manipulador da rota.
  • rsp = bs.on_process_input(request) - Chame o método on_process_input do business service.
  • return rsp - Retorne a resposta.

/posts endpoint

############################
# operações CRUD de posts    #
############################

@app.get("/posts")
def get_posts():
    with Session(engine) as session:
        posts = session.exec(select(Post)).all()
        return posts
    
@app.get("/posts/{post_id}")
def get_post(post_id: int):
    with Session(engine) as session:
        post = session.get(Post, post_id)
        return post
    
@app.post("/posts")
def create_post(post: Post):
    with Session(engine) as session:
        session.add(post)
        session.commit()
        return post

Este endpoint é usado para realizar operações CRUD no objeto Post.

Não há muito a dizer aqui, apenas a definição das rotas para obter todos os posts, obter um post por ID e criar um post.

Tudo é feito usando o ORM sqlmodel.

/comments endpoint

############################
# operações  CRUD de comments #
############################


@app.get("/comments")
def get_comments():
    with Session(engine) as session:
        comments = session.exec(select(Comment)).all()
        return comments
    
@app.get("/comments/{comment_id}")
def get_comment(comment_id: int):
    with Session(engine) as session:
        comment = session.get(Comment, comment_id)
        return comment
    
@app.post("/comments")
def create_comment(comment: Comment):
    with Session(engine) as session:
        session.add(comment)
        session.commit()
        return comment

Este endpoint é usado para realizar operações CRUD no objeto Comment.

Não há muito a dizer aqui, apenas a definição das rotas para obter todos os comentários, obter um comentário por ID e criar um comentário.

Tudo é feito usando o ORM sqlmodel.

Solução de Problemas

Como executar o aplicativo FastAPI em modo autônomo

Você sempre pode executar um aplicativo Flask autônomo com o seguinte comando:

python3 /irisdev/app/community/app.py

Observação: você deve estar dentro do contêiner para executar este comando.

docker exec -it iris-fastapi-template-iris-1 bash

Reinicie o aplicativo no IRIS

Fique no modo DEBUG, faça várias chamadas para o aplicativo e as alterações serão refletidas no aplicativo.

Como acessar o Portal de Gerenciamento do IRIS

Você pode acessar o Portal de Gerenciamento do IRIS acessando http://localhost:53795/csp/sys/UtilHome.csp.

Execute este template localmente

Para isso, você precisa ter o IRIS instalado em sua máquina.

Em seguida, você precisa criar um namespace chamado IRISAPP.

Instale os requisitos.

Instale IoP :

#init iop
iop --init

# load production
iop -m /irisdev/app/community/interop/settings.py

# start production
iop --start Python.Production

Configure o aplicativo no portal de segurança.

0
0 43
Artigo Heloisa Paiva · Out. 20, 2024 6m read

Flask_logo

Descrição

Este é um modelo para um aplicativo Flask que pode ser implantado no IRIS como um aplicativo Web nativo.

Instalação

  1. Clone o repositório
  2. Crie um ambiente virtual
  3. Instale os requisitos
  4. Rode o arquivo docker-compose
git clone
cd iris-flask-template
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
docker-compose up

Uso

A URL de base http://localhost:53795/flask/.

Endpoints

  • /iris - Retorna um objeto JSON com as 10 principais classes presentes no namespace IRISAPP.
  • /interop - Um endpoint de ping para testar o framework de interoperabilidade do IRIS
  • /posts - Um simples enpoint CRUD para um objeto de Post
  • /comments - Um enpoint simples de CRUD para o objeto de comentário

Como desenvolver deste template

Veja o artigo de introdução ao WSGI wsgi-introduction.

TL;DR: Você pode ativar ou desativar o sinalizador DEBUG no portal de segurança para que as alterações sejam refletidas no aplicativo à medida que você desenvolve.

Apresentação do código

app.py

Este é o arquivo principal do aplicativo. Ele contém o aplicativo Flask e os endpoints.

from flask import Flask, jsonify, request
from models import Comment, Post, init_db

from grongier.pex import Director

import iris

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'iris+emb://IRISAPP'

db = init_db(app)
  • from flask import Flask, jsonify, request: Importa a livraria Flask
  • from models import Comment, Post, init_db: Importa os modelos e a função de inicialização de base de dados
  • from grongier.pex import Director: Importa a classe Director para vincular o app flask à framework de interoperabilidade do IRIS
  • import iris: Importa a livraria IRIS
  • app = Flask(__name__): Cria uma aplicação Flask
  • app.config['SQLALCHEMY_DATABASE_URI'] = 'iris+emb://IRISAPP': Define o URI da base de dados ao namespace IRISAPP
    • O esquema de URI iris+emb é usado para conectar ao IRIS como uma conexão embutida (sem necessidade de uma instância IRIS separada
  • db = init_db(app): Inicialize a base de dados com aplicação Flask.

models.py

O arquivo contem os modelos SQLAlchemy para a aplicação.

from dataclasses import dataclass
from typing import List
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

@dataclass
class Comment(db.Model):
    id:int = db.Column(db.Integer, primary_key=True)
    content:str = db.Column(db.Text)
    post_id:int = db.Column(db.Integer, db.ForeignKey('post.id'))

@dataclass
class Post(db.Model):
    __allow_unmapped__ = True
    id:int = db.Column(db.Integer, primary_key=True)
    title:str = db.Column(db.String(100))
    content:str = db.Column(db.Text)
    comments:List[Comment] = db.relationship('Comment', backref='post')

Não há muito o que dizer aqui, os modelos são definidos como classes de dados e são subclasses da classe db.Model

O uso do atributo __allow_unmapped_ é necessário para permitir a criação do objeto Post sem o atributo comments

dataclasses são usadas para ajudar com a serialização de objetos ao JSON

A função init_db inicializa a base de dados com a aplicação Flask.

def init_db(app):
    db.init_app(app)

    with app.app_context():
        db.drop_all()
        db.create_all()
        # Create fake data
        post1 = Post(title='Post The First', content='Content for the first post')
        ...
        db.session.add(post1)
        ...
        db.session.commit()
    return db
  • db.init_app(app): Inicializa a base de dados com a aplicação Flask
  • with app.app_context(): Cria um contexto para a aplicação
  • db.drop_all(): Descarta todas as tabelas na base de dados
  • db.create_all(): Cria todas as tabelas na base de dados
  • Cria dados falsos para a aplicação
  • retorna o objeto de base de dados

/iris endpoint

######################
# IRIS Query exemplo#
######################

@app.route('/iris', methods=['GET'])
def iris_query():
    query = "SELECT top 10 * FROM %Dictionary.ClassDefinition"
    rs = iris.sql.exec(query)
    # Converte o resultado em uma lista de dicionários
    result = []
    for row in rs:
        result.append(row)
    return jsonify(result)

Esse endpoint executa uma query na base de dados IRIS e retorna as top 10 classes presentes no namespace IRISAPP

/interop endpoint

########################
# IRIS interop exemplo #
########################
bs = Director.create_python_business_service('BS')

@app.route('/interop', methods=['GET', 'POST', 'PUT', 'DELETE'])
def interop():
    
    rsp = bs.on_process_input(request)

    return jsonify(rsp)

Este endpoint é usado para testar a estrutura de interoperabilidade do IRIS. Ele cria um objeto de Serviço de Negócio e o vincula ao aplicativo Flask.

Observação: O objeto bs deve estar fora do escopo da solicitação para mantê-lo ativo.

  • bs = Director.create_python_business_service('BS'): Cria um objeto Business Service chamado 'BS'
  • rsp = bs.on_process_input(request): Chama o método on_process_input do objeto Business Service com o objeto de requisição como um argumento

/posts endpoint

############################
# operações CRUD para posts    #
############################

@app.route('/posts', methods=['GET'])
def get_posts():
    posts = Post.query.all()
    return jsonify(posts)

@app.route('/posts', methods=['POST'])
def create_post():
    data = request.get_json()
    post = Post(title=data['title'], content=data['content'])
    db.session.add(post)
    db.session.commit()
    return jsonify(post)

@app.route('/posts/<int:id>', methods=['GET'])
def get_post(id):
    ...

Este endpoint é usado para realizar operações CRUD no objeto Post

Graças ao módulo dataclasses, o objeto Post pode ser facilmente serializado para JSON.

Aqui, usamos o método query do sqlalchemy para obter todos os posts e os métodos add e commit para criar um novo post

/comments endpoint

############################
# operações CRUD para comentários  #
############################

@app.route('/comments', methods=['GET'])
def get_comments():
    comments = Comment.query.all()
    return jsonify(comments)

@app.route('/comments', methods=['POST'])
def create_comment():
    data = request.get_json()
    comment = Comment(content=data['content'], post_id=data['post_id'])
    db.session.add(comment)
    db.session.commit()
    return jsonify(comment)

@app.route('/comments/<int:id>', methods=['GET'])
def get_comment(id):
    ...

Este endpoint é usado para realizar operações CRUD no objeto Comment.

O objeto Comment está vinculado ao objeto Post por uma chave estrangeira.

Solução de Problemas

Como executar o aplicativo Flask em modo autônomo

Você sempre pode executar um aplicativo Flask autônomo com o seguinte comando:

python3 /irisdev/app/community/app.py

Nota: você deve estar dentro do container para rodar este comando

docker exec -it iris-flask-template-iris-1 bash

Reinicie a aplicação no IRIS

Esteja no modo DEBUG, faça várias chamadas para o aplicativo e as alterações serão refletidas no aplicativo.

Como acessar o Portal de Gerenciamento do IRIS

Você pode acessar o Portal de Gerenciamento do IRIS acessandohttp://localhost:53795/csp/sys/UtilHome.csp.

Rode este template localmente

Para isso, você precisa ter o IRIS instalado em sua máquina.

Em seguida, você precisa criar um namespace chamado IRISAPP.

Instale os requisitos.

Instale IoP :

#init iop
iop --init

# carregue a produção 
iop -m /irisdev/app/community/interop/settings.py

# iniicie a produção
iop --start Python.Production

Configure a aplicação no portal de Segurança

0
0 48
Artigo Heloisa Paiva · Out. 14, 2024 9m read

Este programa de demonstração é usado para mostrar como um perfil FHIR personalizado pode ser empregado para validar a conformidade dos dados. O guia de implementação FHIR personalizado foi desenvolvido com base na Versão R4 do FHIR, e, neste exemplo, implementa a extensão do recurso Organização para validar a conformidade dos dados.

Instalação

  1. Faça o Download do projeto via Git clone.
  2. Execute docker-compose up -d para criar e iniciar o contêiner, a execução inicial baixará as imagens de contêiner necessárias e a execução do script levará de 5 a 10 minutos (dependendo da máquina). O InterSystems IRIS for Health image será criado, então o servidor FHIR será instalado e a especificação FHIR personalizada será importada para que possa ser usada para validar os dados.
  3. Importe os arquivos de caso de teste de TestCases no Postman para ver como as várias restrições FHIR são validadas 4.Depois que o contêiner for iniciado, você poderá ver o conteúdo doCustom IG.

Estrutura do código

FHIRValidation
├─ ExampleIG                        
│  ├─ ig.ini
│  ├─ input
│  │  ├─ fsh
│  │  │  ├─ alias.fsh
│  │  │  ├─ codesystems.fsh
│  │  │  ├─ organization.fsh
│  │  │  └─ valuesets.fsh
│  │  └─ pagecontent
│  │     └─ index.md
│  └─ sushi-config.yaml
├─ README.md
├─ README_zh.md
├─ TestCases
│  └─ FHIR Profile-based Validation  testcases.postman_collection.json
├─ docker-compose.yml
└─ image-iris
   ├─ Dockerfile
   └─ src
      ├─ FullIG
      ├─ IGPackages
      │  ├─ hl7.fhir.uv.extensions.r4#5.1.0.tgz
      │  ├─ hl7.terminology.r4#6.0.2.tgz
      │  └─ package.tgz
      └─ init
         └─ init.sh

Examplo IG

Todos os arquivos neste subdiretório são códigos-fonte SUSHI da especificação FHIR personalizada.

Casos de teste

Este subdiretório contém scripts de caso de teste baseados na API REST do FHIR, que precisam ser importados para o Postman

image-iris

Este subdiretório contém os arquivos necessários para a imagem InterSystems IRIS for Health: └─ src ├─ FullIG Este diretório armazena o IG FHIR personalizado gerado porSUSHI ├─ IGPackages Este diretório contém os arquivos de pacote para IGs FHIR personalizados └─ ini tEste diretório contém os scripts de inicialização da imagem Docker IRIS

Introdução ao pacote FHIR

A organização HL7 recomenda o uso de guias de implementação (Guia de Implementação](https://build.fhir.org/ig/FHIR/ig-guidance/)) para explicar como utilizar a especificação FHIR. Além de instruções para leitura por desenvolvedores (por exemplo, HTML), os guias de implementação geralmente incluem artefatos legíveis por máquina e aplicáveis diretamente, que podem ser usados para direcionar tarefas como geração de código e validação de dados.

O Guia de Implementação FHIR usa a especificação Pacote NPM para gerenciar dependências. Todas as definições de estrutura (StructureDefinition), conjuntos de valores (ValueSet) e outros recursos cobertos pelo guia são agrupados em um único pacote que pode ser usado pelo servidor FHIR para ler a especificação, gerar código do cliente ou realizar verificações de qualidade de dados.

O guia de implementação gerado pela ferramenta SUSHI contém vários arquivos de pacote. Neste exemplo, image-iris/src/IGPackages/package.tgz é o pacote gerado, que pode ser diretamente importado pelo Servidor FHIR IRIS. É importante observar que, além dos pacotes de recursos centrais (por exemplo, hl7.fhir.r4.core),a especificação FHIR completa precisa referenciar pacotes de recursos adicionais, como terminologia, extensões e assim por diante.

A documentação atual do mecanismo de referência da especificação FHIR ainda não está completa. Por exemplo, com base na versão R4 da especificação FHIR, além de referenciar hl7.fhir.r4.core, ela também precisa referenciar [hl7.fhir.uv.extensions.r4#5.1.0](https://simplifier.net/packages/hl7.fhir.uv.extensions.r4/ 5.1.0) e hl7.terminology.r4#6.0.2. Essas referências estão documentadas naversão R5mas não declaradas na versão R4, então o desenvolvedor precisa adicioná-las durante o processo de desenvolvimento.

Nesse caso, esses pacotes foram baixados na pasta image-iris/src/IGPackages e serão carregados como dependências antes da personalização do guia de implementação FHIR.

Introdução à validação FHIR

Veja a seção Recursos de Validação da especificação FHIR. A especificação FHIR foi projetada com mecanismos de verificação de qualidade de dados para uma ampla variedade de elementos, incluindo estruturas de dados, bases de atributos, campos de valor, ligações de código, restrições etc. A organização HL7, na especificação FHIR, não define qual intensidade de controle de qualidade seguir, mas recomenda que o princípio detolerância seja aplicado aos dados FHIR.

Para repositórios FHIR que armazenam recursos FHIR, garantir a qualidade dos dados é um pré-requisito para tornar a indústria da saúde valiosa e garantir a segurança das práticas de saúde. Portanto, ao construir um esquema de compartilhamento e troca de dados baseado em repositórios FHIR, mesmo que dados que não atendam aos requisitos de qualidade tenham que ser salvos, deve-se calibrar o sistema para marcar as não-conformidades e promover atividades de governança de dados para salvaguardar a segurança da saúde e os interesses dos consumidores de dados.

ODos vários métodos de validação de dados indicados pela especificação FHIR, o Validador FHIR e as Operações FHIR fornecem a cobertura mais abrangente para validação de qualidade de dados.

Este exemplo usará a operação $validate fornecida pelo InterSystems IRIS for Health para validar dados FHIR que ainda não foram salvos via o parâmetro de perfil. Os usuários também podem modificar o caso de teste para construir um parâmetro HTTP POST para validar o recurso FHIR estoque.

Também deve ser observado que a operação $validate, se chamada corretamente, retornará o resultado da validação via Http 200 e, se houver alguma não-conformidade, uma mensagem de erro será encapsulada no recurso OperationOutcome retornado em vez de identificar o erro via o código Http.

Extensões ao FHIR R4

As seguintes extensões foram feitas ao recurso Organização com base no FHIR R4:

1. Modifique a força de ligação da linguagem

Altere a força de ligação do idioma principal da organização para obrigatório

2. Cardinalidade do campo ativo alterada de 0...1 para 1...1

Isso torna o status do campo ativo um campo obrigatório, com um e somente um elemento

3. Cardinalidade do campo Nome alterada de 0..1 para 1..1

O nome da organização se torna um campo obrigatório com um e somente um elemento. Para referência, hospitais na China podem ter mais de um nome além do nome do hospital se tiverem licenças como um Centro de Emergência, um Centro de Dor Torácica e assim por diante. No entanto, é observado que essas licenças geralmente identificam a capacidade dos serviços prestados pela instituição de saúde em vez do nome legal que ela tem no sistema de registro da organização, e o ciclo de vida de tais licenças não coincide com o ciclo de vida da própria instituição de saúde. Portanto, o nome obtido da licença é apropriadamente considerado como a capacidade de serviço da organização de saúde em vez do nome exclusivo da organização. No FHIR, o nome derivado da capacidade de serviço pode ser fornecido através do recurso HealthcareService, que pode ser mais apropriadamente usado para expressar o conceito acima estabelecendo um relacionamento de referência muitos-para-um com o recurso Organização

4.Aumento no tipo de organização de instituições médicas

De acordo com os tipos de organização do padrão nacional chinês GB/T 20091-2021, os CodeSystem organizationtype-code-system e ValueSet organizationtype-vs são adicionados respectivamente, e a extensão mdm-organizationTypeExtension é adicionada ao recurso Organização através de Extensão. A extensão mdm-organizationTypeExtension é adicionada ao recurso Organização para que o recurso possa ser usado para representar o tipo de organização que identifica os tipos de organização chineses. A extensão é implementada fatiando a Extensão com uma cardinalidade de 1..1 para que o recurso Organização de Saúde deva ter um elemento de tipo de organização.

5. Restrições nos números de identificação de organizações de saúde

O padrão base FHIR não inclui o tipo do código de crédito social unificado para organizações chinesas, por esse motivo o CodeSystem cs-identifierType-code-system é adicionado e o Identificador é fatiado de acordo com seu tipo, para que ele possa expressar o código de crédito social. E o formato do código de crédito social segue as seguintes restrições:

  1. identifier.use deve assumir o valor oficial, ou seja, uso oficial/oficial
  2. identifier.type DEVE seguir cs-identifierType-code-system, system DEVE ser o uri do codesystem e code DEVE ser “USCC”.
  3. identifier.value deve seguir a restrição personalizada uscc-length-18, o campo deve ter 18 dígitos de comprimento, dos quais os primeiros 17 dígitos devem ser numéricos e o último 1 dígito deve ser numérico ou alfabético

Lista de Casos de Teste

1. Sem perfil - Tudo OK

O perfil correspondente do recurso não é declarado, portanto, o Servidor FHIR não validará os valores dos atributos no recurso e retornará apenas Tudo OK.

2. Campo desconhecido

Um atributo não definido isNational foi adicionado ao recurso, portanto, o mecanismo de validação retornou um erro de elemento não reconhecido

3. Cardinalidade errada - menos

Neste IG, a cardinalidade do atributo de nome do recurso Organização foi modificada para 1..1, o que significa que deve haver e somente um nome de organização. O nome não é preenchido neste caso de teste e, portanto, a validação de dados falha. Além disso, pode-se observar que Identifier.type foi estendido para incluir o Código de Crédito Social Uniforme como um tipo de identificador, que não está incluído na especificação FHIR R4, mas a força da ligação de código para este campo é apenas EXEMPLO, o que não força restrições. Portanto, o mecanismo de validação retorna a informação de nível de valor do campo de código não-conformidade sem relatar um erro.

4.Força de ligação

Neste Guia de Implementação (IG), a força de ligação do código do atributo de idioma da organização foi alterada para "obrigatório". Isso significa que o valor do campo deve estar de acordo com o conjunto de valores http://hl7.org/fhir/ValueSet/languages. No caso de teste onde o campo recebe o valor "wrong language" (idioma incorreto), como esse valor não está presente no conjunto de valores obrigatório, a validação resultará em um erro crítico

5.Valor errado

Neste IG, o campo de valor para o tipo de organização vem de organizationtype-code-system, portanto, quando o valor de code no elemento de extensão do tipo mdm-organizationTypeExtension, que tem um valor de "999", que não está no campo de valor, resultará em um erro de nível de erro.

6. Invariante falha

Neste IG, o código de crédito social de uma organização deve seguir a restrição personalizada uscc-length-18 (o campo deve ter 18 dígitos de comprimento, onde os primeiros 17 dígitos devem ser numéricos e o último 1 dígito deve ser numérico ou alfabético), e, portanto, violar essa restrição quando o último dígito for o caractere “%” resultará em um erro.

7.Perfil falha

Um único perfil para uma definição de recurso contém várias restrições, portanto, todos os problemas que não satisfazem o perfil serão detectados durante a validação, como os seguintes problemas neste exemplo:

  1. código de idioma errado
  2. tipo de organização errado
  3. campo de nome ausente
0
0 33
Artigo Danusa Calixto · Abr. 8, 2024 6m read

image

Este artigo abordará a transferência do controle do provisionamento do InterSystems Kubernetes Operator e o início da sua jornada com a gestão da sua própria "nuvem" de soluções InterSystems através de práticas Git Ops. Esse padrão de implantação também é o caminho de execução para o PID^TOO||| Motor de Resolução de Identidade de Respiração FHIR.

Git Ops

Recomendo que você faça sua própria pesquisa ou pergunte ao seu LLM favorito sobre o Git Ops, mas posso parafrasear aqui como o entendemos. Git Ops é um paradigma de implantação alternativo, onde o próprio Cluster Kubernetes "extrai" atualizações de manifestos que residem no controle de origem para gerenciar o estado das suas soluções, tornando o "Git" uma parte essencial do nome.

Pré-requisitos

  • Provisionar um Cluster Kubernetes, isso foi testado em clusters EKS, GKE e MicroK8s
  • Provisionar um GitLab, GitHub ou outro repositório Git que possa ser acessado pelo seu Cluster Kubernetes

Argo CD

A estrela do show aqui é o ArgoCD, que fornece uma abordagem declarativa de entrega contínua com uma IU extremamente bem feita. Usar o gráfico no seu cluster é muito fácil, exigindo apenas alguns toques.

kubectl create namespace argocd
kubectl apply -n argocd -f \
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Vamos fazer login na IU do ArgoCD no seu Cluster Kubernetes. Para isso, você precisa obter o segredo que foi criado para a IU e configurar um encaminhamento de porta para torná-lo acessível no seu sistema.

Obtenha o segredo
Descriptografe e coloque-o na área de transferência. image

Encaminhamento de porta
Redirecione a porta 4000 (ou qualquer outra) para seu host local

image

IU
Acesse https://0.0.0.0:4000, forneça o segredo na tela de login e faça login.

image

InterSystems Kubernetes Operator (IKO)

As instruções para obter o gráfico IKO Helm estão na própria documentação. Depois de obtê-las, confira no seu repositório git em uma ramificação de recurso. Eu forneceria um repositório de amostra, mas infelizmente não posso fazer isso sem uma violação da redistribuição, porque o gráfico não parece estar disponível em um repositório público.

Crie você mesmo uma ramificação de recurso no seu repositório git e descompacte o gráfico IKO Helm em um único diretório. Conforme abaixo, é o iko/iris_operator_amd-3.5.48.100 fora da raiz do repositório.

Na ramificação feature/iko como exemplo:

├── iko
│   ├── AIKO.pdf
│   └── iris_operator_amd-3.5.48.100
│       ├── chart
│       │   └── iris-operator
│       │       ├── Chart.yaml
│       │       ├── templates
│       │       │   ├── apiregistration.yaml
│       │       │   ├── appcatalog-user-roles.yaml
│       │       │   ├── cleaner.yaml
│       │       │   ├── cluster-role-binding.yaml
│       │       │   ├── cluster-role.yaml
│       │       │   ├── deployment.yaml
│       │       │   ├── _helpers.tpl
│       │       │   ├── mutating-webhook.yaml
│       │       │   ├── service-account.yaml
│       │       │   ├── service.yaml
│       │       │   ├── user-roles.yaml
│       │       │   └── validating-webhook.yaml
│       │       └── values.yaml

Configuração do IKO
Crie o namespace isc e adicione o segredo para containers.intersystems.com nele.

kubectl create ns isc

kubectl create secret docker-registry \
pidtoo-pull-secret --namespace isc \
--docker-server=https://containers.intersystems.com \
--docker-username='ron@pidtoo.com' \
--docker-password='12345'

Isso deve concluir a configuração do IKO e permitir que ele seja delegado inteiramente por Git Ops para o Argo CD.

Conecte o Git ao Argo CD

Essa é uma etapa simples na UI do Argo CD para conectar o repositório. Essa etapa APENAS "conecta" o repositório, a configuração adicional estará no próprio repositório.

image

Declare a ramificação ao Argo CD

Configure o Kubernetes para sondar a ramificação pelo values.yml do Argo CD no gráfico do Argo CD. A maioria desses locais no repositório git fica por sua conta, mas a maneira teimosa de declarar as coisas no seu repositório pode estar em um paradigma "App de Apps".

Considere criar a estrutura de pastas abaixo e os arquivos que precisam ser criados como um índice a seguir:

├── argocd
│   ├── app-of-apps
│   │   ├── charts
│   │   │   └── iris-cluster-collection
│   │   │       ├── Chart.yaml  ## Chart
│   │   │       ├── templates
│   │   │       │   ├── iris-operator-application.yaml  ## IKO As Application
│   │   │       └── values.yaml ## Application Chart Values
│   │   └── cluster-seeds
│   │       ├── seed.yaml  ## Cluster Seed

Gráfico

apiVersion: v1
description: 'pidtoo IRIS cluster'
name: iris-cluster-collection
version: 1.0.0
appVersion: 3.5.48.100
maintainers:
  - name: intersystems
    email: support@intersystems.com  

IKO como aplicativo

apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: iko
      namespace: argocd
    spec:
      destination:
        namespace: isc
        server: https://kubernetes.default.svc
      project: default
      source:
        path: iko/iris_operator_amd-3.5.48.100/chart/iris-operator
        repoURL: {{ .Values.repoURL }}
        targetRevision: {{ .Values.targetRevision }}
      syncPolicy:
        automated: {}
        syncOptions:
        - CreateNamespace=true  

Valores de gráfico do aplicativo IKO

targetRevision: main
repoURL: https://github.com/pidtoo/gitops_iko.git

Semente do cluster

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: gitops-iko-seed
  namespace: argocd
  labels:
    isAppOfApps: 'true'
spec:
  destination:
    namespace: isc
    server: https://kubernetes.default.svc
  project: default
  source:
    path: argocd/app-of-apps/charts/iris-cluster-collection
    repoURL: https://github.com/pidtoo/gitops_iko.git
    targetRevision: main
  syncPolicy:
    automated: {}
    syncOptions:
    - CreateNamespace=true

Semeie o cluster!

Essa é a última palavra sobre a interação com seus aplicativos Argo CD/IKO Cluster, o resto fica por conta do Git!

kubectl apply -n argocd -f argocd/app-of-apps/cluster-seeds/seed.yaml

Mesclar com o principal

Ok, é aqui que vemos como fomos na IU. Você deve começar imediatamente a ver no Argo CD os aplicativos começando a ganhar vida.

A visão dos apps:
image

Visão do InterSystems Kubernetes Operator
imageimage

Bem-vindo ao GitOps com o InterSystems Kubernetes Operator!

As demonstrações do Git são as melhores! - Live de 19 de outubro de 2023

Ron Sweeney, Arquiteto Principal, Integration Required, LLC (PID^TOO) Dan McCracken, COO, Devsoperative, INC

0
0 104
Artigo Danusa Calixto · Nov. 28, 2023 8m read

Olá, Comunidade,
Neste artigo, vou apresentar meu aplicativo iris-mlm-explainer

Esse aplicativo da Web se conecta ao InterSystems Cloud SQL para criar, treinar, validar e prever modelos de ML, fazer previsões e mostrar um painel com todos os modelos treinados e uma explicação sobre o funcionamento de um modelo de machine learning ajustado. O painel fornece plotagens interativas de desempenho do modelo, importância do recurso, contribuições do recurso para previsões individuais, plotagens de dependência parcial, valores SHAP (interação), visualização de árvores de decisões individuais etc.

Pré-requisitos

  • Você precisa ter uma conta no InterSystems Cloud SQL.
  • Você precisa ter o <a book="" en="" getting-started-installing-git="" git-scm.com="" https:="" v2="">Git</a> instalado localmente.
  • Você precisa ter o <a downloads="" https:="" www.python.org="">Python3</a> instalado localmente.  

Primeiros Passos

Vamos seguir as etapas abaixo para criar e visualizar o painel explicativo de um modelo:

  • Etapa 1 : fazer o git pull/clone do repositório

  • Etapa 2 : fazer login no portal de serviços do InterSystems Cloud SQL

    • Etapa 2.1 : adicionar e gerenciar arquivos
    • Etapa 2.2 : importar DDL e arquivos de dados
    • Etapa 2.3 : criar modelo
    • Etapa 2.4 : treinar modelo
    • Etapa 2.5 : validar modelo
  • Etapa 3 : ativar o ambiente virtual do Python

  • Etapa 4 : executar o aplicativo da Web para previsão

  • Etapa 5 : explorar e o painel explicativo

Etapa 1 : fazer o git pull/clone do repositório

Então, vamos começar com a primeira etapa

Crie uma pasta e faça o git pull/clone do repositório em qualquer diretório local

git clone https://github.com/mwaseem75/iris-mlm-explainer.git

 

Etapa 2 : fazer login no portal de serviços do InterSystems Cloud SQL

Faça login no InterSystems Cloud Service Portal
image

 

 

Selecione a implantação executada

image

 

Etapa 2.1 : adicionar e gerenciar arquivos

Clique em "Add and Manage Files" (Adicionar e gerenciar arquivos)

image

O repositório contém os arquivos USA_Housing_tables_DDL.sql(DDL para criar tabelas), USA_Housing_train.csv(dados de treinamento) e USA_Housing_validate.csv(para validação) na pasta de conjuntos de dados. Selecione o botão de upload para adicionar esses arquivos.

Adicionar arquivos

Etapa 2.2 : importar DDL e arquivos de dados

Clique em "Import files" (Importar arquivos), no botão de opção das declarações DDL ou DML e no botão "Next" (Próximo)

Importar DDL

Clique no botão de opção do Intersystems IRIS e em "Next"

IsIRIS

Selecione o arquivo USA_Housing_tables_DDL.sql e pressione o botão para importar arquivos

Importar arquivo DDL

Clique em "Import" na caixa de diálogo de confirmação para criar a tabela

confirmar importação

importação concluída

Clique nas ferramentas da Query em SQL para verificar se as tabelas foram criadas

conferir se as tabelas foram criadas

Importar arquivos de dados

Clique em "Import files" (Importar arquivos), no botão de opção dos dados CSV e no botão "Next" (Próximo)

csv1

Selecione o arquivo USA_Housing_train.csv e clique no botão "Next"

csv2

 

Selecione o arquivo USA_Housing_train.csv na lista suspensa, marque para importar o arquivo como linha de cabeçalho, selecione "Field names in header row match column names in selected table" (Os nomes dos campos na linha de cabeçalho correspondem aos nomes das colunas na tabela selecionada) e clique em "Import files"

csv3

Clique em "Import" na caixa de diálogo de confirmação

csv4

Confira se 4000 linhas foram atualizadas

csv5

Repita as mesmas etapas para importar o arquivo USA_Housing_validate.csv, que contém 1500 registros

csv6

Etapa 2.3 : criar modelo

Clique em "IntegratedML tools" (ferramentas do IntegratedML) e selecione "Create Panel" (Criar painel).

Insira "USAHousingPriceModel" no campo de nome do modelo, selecione a tabela "usa_housing_train" e "Price" no menu suspenso "Field to predict" (Campo para prever). Clique no botão "Create model" para criar o modelo

criar modelo

 

Etapa 2.4 : treinar modelo

Selecione "Train Panel" (Treinar painel), escolha "USAHousingPriceModel" na lista suspensa "Model to train" (Modelo a treinar) e insira "USAHousingPriceModel_t1" no campo de nome do modelo a treinar

TREINAR1

O modelo será treinado após a conclusão do status de execução

TREINAR2

 

Etapa 2.5 : validar modelo

Selecione "Validate Panel" (Validar painel), escolha "USAHousingPriceModel_t1" na lista suspensa "Trained model to validate" (Modelo treinado a validar), selecione "usa_houseing_validate" na lista suspensa "Table to validate model from" (Tabela para validar o modelo) e clique no botão "Validate model" (Validar modelo)

image

Clique em "Show validation metrics" para ver as métricas

mostrar validação

Clique no ícone de gráfico para ver o gráfico "Prediction VS Actual" (Previsão x Real)

gráfico de validação

 

Etapa 3 : ativar o ambiente virtual do Python

O repositório já contém uma pasta de ambiente virtual do python (venv) com as bibliotecas necessárias.

Tudo o que precisamos fazer é ativar o ambiente
No Unix ou MacOS:

$source venv/bin/activate

No Windows:

venv\scripts\activate

###Etapa 4 : definir parâmetros de conexão do InterSystems Cloud SQL

O repositório contém o arquivo config.py. Basta abrir e definir os parâmetros
image
Coloque os mesmos valores usados no InterSystems Cloud SQL
image

 

Etapa 4 : executar o aplicativo da Web para previsão

Execute o comando abaixo no ambiente virtual para iniciar nosso aplicativo principal

python app.py

image

Acesse http://127.0.0.1:5000/ para executar o aplicativo

image

Insira "Age of house" (Idade da casa), "No of rooms" (Nº de cômodos), "No of bedroom" (Nº de quartos) e "Area population" (População da área) para obter a previsão

image

Etapa 5 : explorar e o painel explicativo

Por fim, execute o comando abaixo no ambiente virtual para iniciar nosso aplicativo principal

python expdash.py

imageimage
image

Acesse http://localhost:8050/ para executar o aplicativo
image

O aplicativo listará todos os modelos treinados com nosso "USAHousingPriceModel". Clique no hyperlink "Go to dashboard" (Acessar painel) para visualizar a explicação sobre o modelo

Importância dos recursos. Quais recursos tiveram o maior impacto?
image

Métricas quantitativas para o desempenho do modelo, Qual é a diferença entre o valor previsto e o observado?
image

Previsão e Como cada recurso contribuiu para a previsão?
image

Ajuste os valores dos recursos para mudar a previsão
image

Resumo Shap, Ordenamento dos recursos por valores shap
image

Resumo de interações, Ordenamento dos recursos por valor de interação shap
image

Árvores de decisões, Exibição de árvores de decisões individuais dentro do Random Forest
image

Obrigado

0
0 87
Artigo Danusa Calixto · Abr. 4, 2023 13m read

Bem-vindo ao capítulo seguinte da minha série sobre CI/CD, onde discuto possíveis abordagens de desenvolvimento de software com tecnologias da InterSystems e GitLab.

Hoje, vamos falar sobre interoperabilidade.

Problema

Em uma produção de interoperabilidade ativa, há dois fluxos de processo separados: uma produção em funcionamento que processa as mensagens e um fluxo de processo CI/CD que atualiza o código, a configuração da produção e as configurações padrão do sistema.

Claramente, os processos CI/CD afetam a interoperabilidade. No entanto, as perguntas são:

  • O que acontece exatamente durante uma atualização?
  • O que precisamos fazer para minimizar ou eliminar o tempo de inatividade da produção durante uma atualização?

Terminologia

  • Host de Negócio (Business Host - BH) - um elemento configurável da Produção da Interoperabilidade: Serviço de Negócio (Business Service - BS), Processo de Negócio ( Business Process - BP, BPL) ou Operação de Negócio (Business Operation, BO).
  • Job do Host de Negócio (Business Host Job) - job do InterSystems IRIS que executa o código do Host de Negócio e é gerenciado pela produção de interoperabilidade.
  • Produção - coleção interconectada de Hosts de Negócio.
  • Configurações Padrão do Sistema (System Default Settings - SDS) - valores específicos do ambiente de instalação do InterSystems IRIS.
  • Mensagem Ativa - uma solicitação que está sendo processada por um Job do Host de Negócio. Um Job do Host de Negócio só pode ter uma Mensagem Ativa. O Job do Host de Negócio que não tem uma Mensagem Ativa está inativo.

O que está acontecendo?

Vamos começar com o ciclo de vida da produção.

Início da Produção

Primeiro, a Produção pode ser iniciada. Só pode ser executada uma produção por namespace ao mesmo tempo, e em geral (a menos que você saiba o que e porque está fazendo isso), apenas uma produção deve ser executada por namespace. Alternar várias vezes em um namespace entre duas ou mais produções diferentes não é recomendado. Ao iniciar a produção, todos os Hosts de Negócio habilitados definidos nela são inicializados. Se alguns Hosts de Negócio não inicializarem, isso não afeta a inicialização da Produção.

Dicas:

  • Comece a produção no Portal de Gerenciamento de Sistemas ou ao chamar: ##class(Ens.Director).StartProduction("ProductionName")
  • Execute código arbitrário na inicialização da Produção (antes que qualquer Job do Host de Negócio seja inicializado) ao implementar um método OnStart
  • A inicialização da Produção é um evento auditável. Você sempre pode ver quem e quando fez o que no Log de Auditoria.

Atualização da Produção

Após a inicialização da Produção, Ens.Director monitora continuamente a produção em execução. Há dois estados de produção: o estado desejado, definido na classe da produção e nas Configurações Padrão do Sistema, e o estado em execução, os jobs atualmente em execução com configurações aplicadas quando os jobs foram criados. Se os estados desejado e atual forem idênticos, está tudo bem, mas a produção pode (e deve) ser atualizada se houver uma diferença. Geramente, você vê isso como um botão vermelho Update na página de Configurações da Produção no Portal de Gerenciamento de Sistemas.

A atualização da produção significa uma tentativa de corresponder o estado atual da Produção ao estado visado.

A execução de ##class(Ens.Director).UpdateProduction(timeout=10, force=0) para atualizar a produção faz o seguinte com cada Host de Negócio:

  1. Compara as configurações ativas às configurações de produção/SDS/classe
  2. Se, e apenas se, (1) apresentar uma discrepância, o Host de Negócio será marcado como desatualizado, exigindo uma atualização.

Depois de executar isso para cada Host de Negócio, UpdateProduction cria o conjunto de mudanças:

  • Hosts de Negócio para interromper
  • Hosts de Negócio para inicializar
  • Configurações da produção para atualizar

E, depois disso, aplica essas mudanças.

Dessa forma, "atualizar" as configurações sem mudar nada resulta em nenhum tempo de inatividade da produção.

Dicas:

  • Atualize a produção no Portal de Gerenciamento de Sistemas ou ao chamar: ##class(Ens.Director).UpdateProduction(timeout=10, force=0)
  • O tempo limite de atualização padrão do Portal de Gerenciamento de Sistemas é 10 segundos. Se você sabe que o processamento das mensagens leva mais do que isso, chame Ens.Director:UpdateProduction com um tempo limite maior.
  • O tempo limite da atualização é uma configuração da produção, e você pode mudar para um valor maior. Essa configuração se aplica ao Portal de Gerenciamento de Sistemas.

Atualização do código

UpdateProduction NÃO ATUALIZA BHs com código desatualizado. Esse é um comportamento voltado para a segurança, mas, se você quiser atualizar todos os BHs em execução automaticamente se o código subjacente mudar, siga estas etapas:

Primeiro, carregue e compile desta maneira:

do $system.OBJ.LoadDir(dir, "", .err, 1, .load)
do $system.OBJ.CompileList(load, "curk", .errCompile, .listCompiled)

Agora, listCompiled teria todos os itens que foram realmente compilados (use git diffs para minimizar o conjunto carregado) devido à flag u. Use listCompiled para obter um $lb de todas as classes que foram compiladas:

set classList = ""
set class = $o(listCompiled(""))
while class'="" { 
  set classList = classList _ $lb($p(class, ".", 1, *-1))
  set class=$o(listCompiled(class))
}

Depois disso, calcule uma lista de BHs que precisam de uma reinicialização:

SELECT %DLIST(Name) bhList
FROM Ens_Config.Item 
WHERE 1=1
  AND Enabled = 1
  AND Production = :production
  AND ClassName %INLIST :classList

Por fim, após obter bhList, interrompa e inicie os hosts afetados:

for stop = 1, 0 {
  for i=1:1:$ll(bhList) {
    set host = $lg(bhList, i)
    set sc = ##class(Ens.Director).TempStopConfigItem(host, stop, 0)
  }
  set sc = ##class(Ens.Director).UpdateProduction()
}

Interrupção da produção

As produções podem ser interrompidas, ou seja, uma solicitação pode ser enviada para desativar todos os Jobs do Host de Negócio (com segurança, após lidarem com as mensagens ativas, se houver alguma).

Dicas:

  • Interrompa a produção no Portal de Gerenciamento de Sistemas ou ao chamar: ##class(Ens.Director).StopProduction(timeout=10, force=0)
  • O tempo limite de interrupção padrão do Portal de Gerenciamento de Sistemas é 120 segundos. Se você sabe que o processamento das mensagens leva mais do que isso, chame Ens.Director:StopProduction com um tempo limite maior.
  • O tempo limite de interrupção é uma configuração da produção. Você pode alterar isso para um valor maior. Essa configuração se aplica ao Portal de Gerenciamento de Sistemas.
  • Execute código arbitrário na interrupção da produção ao implementar um método OnStart
  • A interrupção da produção é um evento auditável. Você sempre pode ver quem e quando fez o que no Log de Auditoria.

O importante aqui é que a produção seja a soma total dos Hosts de Negócio:

  • Ao iniciar a produção, todos os Hosts de Negócio habilitados são inicializados.
  • A interrupção da produção também interrompe todos os Hosts de Negócio em execução.
  • A atualização da produção significa calcular um subconjunto de Hosts de Negócio que estão desatualizados, para que sejam interrompidos e, imediatamente depois disso, inicializados novamente. Além disso, um Host de Negócio recém-adicionado é inicializado, e um Host de Negócio excluído da produção é interrompido.

Isso nos leva ao ciclo de vida dos Hosts de Negócio.

Inicialização do Host de Negócio

Os Hosts de Negócio são compostos de Jobs de Hosts de Negócio idênticos (de acordo com um valor de configuração de tamanho do pool). Ao inicializar um Host de Negócio, todos os Jobs de Hosts de Negócio também são inicializados. Eles são inicializados em paralelo.

Jobs de Host de Negócio individuais são inicializados desta maneira:

  1. A interoperabilidade define como job um novo processo que se tornaria um Job de Host de Negócio.
  2. O novo processo é registrado como um job de interoperabilidade.
  3. O código de Host de Negócio e o código do Adapter são carregados na memória do processo.
  4. As configurações relacionadas a um Host de Negócio e Adapter são carregadas na memória. A ordem de precedência é: a. Configurações da Produção (substituem as Configurações de Classe e Padrão do Sistema). b. Configurações Padrão do Sistema (substituem as Configurações de Classe). c. Configurações de classe.
  5. O job está pronto e começa a aceitar mensagens.

Após a conclusão de (4), o Job não pode alterar as configurações ou o código, então quando você importa código novo/igual e configurações padrão do sistema novas/iguais, isso não afeta os jobs de interoperabilidade atualmente em execução.

Interrupção do Hosts de Negócio

Interromper um Job de Host de Negócio significa o seguinte:

  1. A interoperabilidade pede que o Job pare de aceitar mensagens/entradas.
  2. Se houver uma mensagem ativa, o Job de Host de Negócio tem segundos de tempo limite para processar (ao concluir, finalizando o método OnMessage para BO, OnProcessInput para BS, S<int> para BPL BPs e On* para BPs).
  3. Se uma mensagem ativa não for processada até o tempo limite e force=0, ocorrerá a falha da atualização da produção para esse Host de Negócio (voce verá um botão "Update" vermelho no Portal de Gerenciamento de Sistemas).
  4. A interrupção é bem-sucedida se algo nesta lista for verdadeiro:
    • Nenhuma mensagem ativa
    • A mensagem ativa foi processada antes de timeout
    • A mensagem ativa não foi processada antes do tempo limite, MAS force=1
  5. O job é cancelado com interoperabilidade e é interrompido.

Atualização do Host de Negócio

A atualização do Host de Negócio significa a interrupção de todos os Jobs em execução para o Host de Negócio e a inicialização de novos Jobs.

Regras de negócios, de roteamento e DTLs

Todos os Hosts de Negócio são inicializados imediatamente usando as novas versões das Regras de negócios, de roteamento e DTLs assim que ficarem disponíveis. A reinicialização de um Host de Negócio não é necessária nesse caso.

Atualizações offline

Às vezes, no entanto, as atualizações da produção exigem tempo de inatividade de Hosts de Negócio individuais.

Regras dependem de novo código

Considere a situação. Você tem uma Regra de Roteamento X atual que encaminha as mensagens para o Processo de Negócio A ou B com base em critérios arbitrários. Em um novo commit, você adiciona, simultaneamente:

  • Processo de Negócio C
  • Uma nova versão da Regra de Roteamento X, que encaminha mensagens para A, B ou C.

Nesse caso, você não pode só carregar a regra primeiro e depois atualizar a produção. A regra recém-copilada imediatamente começaria a encaminhar as mensagens para o Processo de Negócio C, que o InterSystems IRIS talvez ainda não tenha compilado ou a interoperabilidade ainda não tenha atualizado para usar. Nesse caso, você precisa desativar o Host de Negócio com uma Regra de Roteamento, atualizar o código, atualizar a produção e ativar o Host de Negócio novamente.

Observações:

  • Se você atualizar uma produção usando um arquivo de implantação de produção, todos os BHs afetados são desativados/ativados automaticamente.
  • Para hosts invocados InProc, a compilação invalida o cache de um host específico mantido pelo autor da chamada.

Dependências entre Hosts de Negócio

As dependências entre Hosts de Negócio são fundamentais. Suponha que você tenha os Processos de Negócio A e B, em que A envia mensagens a B. Em um novo commit, você adiciona, simultaneamente:

  • Uma nova versão do Processo A, que define uma nova propriedade X em uma solicitação para B
  • Uma nova versão do Processo B que pode processar uma nova propriedade X

Nesse caso, PRECISAMOS atualizar o Processo B primeiro e o A depois. Você pode fazer isso de uma das seguintes maneiras:

  • Desativar Hosts de Negócio durante a atualização
  • Divida a atualização em duas partes: primeiro, atualize apenas o Processo B e, depois, em uma atualização separada, comece a enviar mensagens para ele do Processo A.

Uma variação mais desafiadora desse tema, em que as novas versões dos Processos A e B são incompatíveis com as versões antigas, exige tempo de inatividade do Host de Negócio.

Filas

Se você sabe que, após a atualização, um Host de Negócio não conseguirá processar mensagens antigas, você precisa garantir que a Fila do Host de Negócio esteja vazia antes da atualização. Para isso, desative todos os Hosts de Negócio que enviam mensagens para o Host de Negócios e espere até que a fila fique vazia.

Mudança de estado nos Processos de Negócio BPL

Primeiro, uma pequena introdução sobre como funcionam os BPs do BPL. Depois de compilar um BP do BPL, duas classes são criadas no pacote com o mesmo nome que o da classe BPL completa:

  • A classe Thread1 contém os métodos S1, S2, ... SN, que corresponde às atividades no BPL
  • A classe Context tem todas as variáveis de contexto, além do próximo estado que o BPL executaria (ou seja, S5)

Além disso, a classe BPL é persistente e armazena as solicitações que estão sendo processadas.

O BPL funciona ao executar os métodos S em uma classe Thread e atualizando de maneira correspondente a tabela da classe BPL, Context e Thread1, em que uma mensagem "em processamento" é uma linha em uma tabela BPL. Após o processamento da solicitação, o BPL exclui as entradas do BPL, Context e Thread. Como os BPs do BPL são assíncronos, um job BPL pode processar simultaneamente várias solicitações ao salvar as informações entre chamadas S e alternar entre diferentes solicitações. Por exemplo, o BPL processou uma solicitação até chegar a uma atividade sync, aguardando uma resposta da BO. Ele salvaria o contexto atual no disco, com a propriedade %NextState (na classe Thread1) definida para o método S de atividade de resposta e trabalharia em outras solicitações até a BO responder. Após a resposta da BO, o BPL carregaria "Context" na memória e executaria o método correspondente a um estado salvo na propriedade %NextState.

Agora, o que acontece quando atualizamos o BPL? Primeiro, precisamos conferir se pelo menos uma destas condições é atendida:

  • Durante a atualização, a tabela Context está vazia, o que significa que nenhuma mensagem ativa está em trabalho.
  • Os Novos Estados são os mesmos que os antigos ou os novos Estados são adicionados após os antigos.

Se pelo menos uma condição for atendida, podemos continuar. Não há solicitações de pré-atualização para processar o BPL pós-atualização ou os Estados são adicionados no final, o que significa que as solicitações antigas também podem ir para lá (supondo que as solicitações de pré-atualização sejam compatíveis com as atividades e o processamento do BPL pós-atualização).

Mas e se você tiver solicitações ativas em processamento e o BPL mudar a ordem dos estados? O ideal é, se você puder esperar, desativar os autores de chamada do BPL e esperar até que a fila esteja vazia. Valide se a tabela Context também está vazia. Lembre-se de que a Fila mostra apenas as solicitações não processadas e a tabela Context armazena as solicitações em trabalho, então um BPL muito ocupado pode mostrar o tamanho da Fila como zero e isso é normal. Depois disso, desative o BPL, realize a atualização e ative todos os Hosts de Negócio desativados anteriormente.

Se isso não for possível (geralmente quando o BPL é muito longo, lembro de atualizar um que demorou cerca de uma semana para processar uma solicitação, ou a janela de atualização é muito curta), use o versionamento do BPL.

Como alternativa, você pode escrever um script de atualização. No script de atualização, mapeie os próximos estados antigos para os próximos estados novos e execute na tabela Thread1 para que o BPL atualizado possa processar solicitações antigas. O BPL precisa ser desativado durante a atualização. Dito isso, é uma situação extremamente rara e geralmente desnecessária, mas, se precisar fazer isso, é dessa maneira.

Conclusão

A interoperabilidade implementa um algoritmo sofisticado para minimizar o número de ações necessárias para atualizar a produção após a alteração do código subjacente. Chame UpdateProduction com um tempo limite seguro em cada atualização de SDS. Para cada atualização de código, você precisa decidir uma estratégia.

Minimizar a quantidade de código compilado usando git diffs ajuda no tempo de compilação, mas "atualizar" o código com ele mesmo e compilá-lo novamente ou "atualizar" as configurações com os mesmos valores não aciona ou exige uma atualização da produção.

Atualizar e compilar Regras de Negócio, Regras de Roteamento e DTLs os torna imediatamente acessíveis sem a atualização da produção.

Por fim, a atualização da produção é uma operação segura e geralmente não requer tempo de inatividade.

Links

O autor gostaria de agradecer a @James MacKeith, @Dmitry Zasypkin e @Regilo Regilio Guedes de Souza pela ajuda inestimável com este artigo.

0
0 65
Artigo Danusa Calixto · Fev. 23, 2023 3m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Primeiro artigo
    • Conceitos básicos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno
    • Como o Git pode ser usado para desenvolver software (fluxos do Git)
  • Segundo artigo
    • Fluxo de trabalho do GitLab — um processo completo do ciclo de vida do software, desde a ideia até o feedback do usuário
    • Entrega Contínua — uma abordagem de engenharia de software em que as equipes produzem software em ciclos curtos, garantindo que o software possa ser lançado de forma confiável a qualquer momento. Seu objetivo é construir, testar e lançar software com mais rapidez e frequência
  • Terceiro artigo
    • Instalação e configuração do GitLab
    • Conexão dos seus ambientes ao GitLab
  • Quarto artigo
    • Configuração da entrega contínua
  • Quinto artigo
    • Contêineres e como (e por que) podem ser usados
  • Sexto artigo
    • Principais componentes para um pipeline de entrega contínua com contêineres
    • Como todos eles trabalham juntos
  • Sétimo artigo
    • Configuração da entrega contínua com contêineres
  • Oitavo artigo
    • Configuração da entrega contínua com o InterSystems Cloud Manager
  • Nono artigo
    • Arquitetura do contêiner
  • Décimo artigo
    • CI/CD para configuração e dados
  • Décimo primeiro artigo
    • Interoperabilidade e CI/CD

Nessa série de artigos, discuti abordagens gerais de entrega contínua. É um tema extremamente vasto e essa série de artigos precisa ser vista mais como uma coleção de receitas do que algo definitivo. Se você deseja automatizar o desenvolvimento, os testes e a entrega do seu aplicativo, a entrega contínua em geral e o GitLab em particular é o melhor caminho. A entrega contínua e os contêineres permitem que você personalize seu fluxo de trabalho conforme necessário.

0
0 175
Artigo Danusa Calixto · Fev. 23, 2023 11m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Git básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de trabalho do GitLab
  • Entrega contínua
  • Instalação e configuração do GitLab
  • CI/CD do GitLab
  • Por que contêineres?
  • Infraestrutura dos contêineres
  • CD usando contêineres

No primeiro artigo, abordamos os fundamentos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno e como o Git pode ser usado para desenvolver software.

No segundo artigo, abordamos o fluxo de trabalho do GitLab: um processo inteiro do ciclo de vida do software e a entrega contínua.

No terceiro artigo, abordamos a instalação e configuração do GitLab e a conexão dos seus ambientes a ele

No quarto artigo, escrevemos uma configuração de CD.

No quinto artigo, falamos sobre contêineres e como (e por que) eles podem ser usados.

No sexto artigo, vamos discutir os principais componentes necessários para executar um pipeline de entrega contínua com contêineres e como eles trabalham juntos.

Neste artigo, criaremos a configuração de entrega contínua discutida nos artigos anteriores.

Fluxo de trabalho

Na nossa configuração de entrega contínua:

  • Enviamos código para o repositório do GitLab
  • Criamos a imagem docker
  • Testamos
  • Publicamos a imagem no nosso registro docker
  • Trocamos o contêiner antigo pela nova versão do registro

Ou em formato gráfico:

Vamos começar.

Criação

Primeiro, precisamos criar nossa imagem.

Nosso código seria, como sempre, armazenado no repositório, a configuração de CD em gitlab-ci.yml. No entanto, além disso (para aumentar a segurança), armazenaríamos vários arquivos específicos do servidor em um servidor de compilação.

GitLab.xml

Contém o código dos hooks de CD. Foi desenvolvido no artigo anterior e disponibilizado no GitHub. É uma pequena biblioteca para carregar código, executar vários hooks e testar código. Como alternativa preferencial, você pode usar submódulos git para incluir este projeto ou algo semelhante no seu repositório. Os submódulos são melhores porque é mais fácil mantê-los atualizados. Uma outra alternativa seria marcar as versões no GitLab e carregá-las com o comando ADD.

iris.key

Chave de licença. Como alternativa, ela pode ser baixada durante a compilação do contêiner em vez de armazenada em um servidor. É bastante arriscado armazenar no repositório.

pwd.txt

Arquivo contendo a senha padrão. Novamente, é bastante arriscado armazená-lo no repositório. Além disso, se você estiver hospedando um ambiente de produção em um servidor separado, ele poderá ter uma senha padrão diferente.

load_ci.script

O script inicial:

  • Ativa a autenticação do SO

  • Carrega GitLab.xml

  • Inicializa as configurações do utilitário GitLab

  • Carrega o código

    set sc = ##Class(Security.System).Get("SYSTEM",.Properties) write:('sc) $System.Status.GetErrorText(sc) set AutheEnabled = Properties("AutheEnabled") set AutheEnabled = $zb(+AutheEnabled,16,7) set Properties("AutheEnabled") = AutheEnabled set sc = ##Class(Security.System).Modify("SYSTEM",.Properties) write:('sc) $System.Status.GetErrorText(sc) zn "USER" do ##class(%SYSTEM.OBJ).Load(##class(%File).ManagerDirectory() _ "GitLab.xml","cdk") do ##class(isc.git.Settings).setSetting("hooks", "MyApp/Hooks/") do ##class(isc.git.Settings).setSetting("tests", "MyApp/Tests/") do ##class(isc.git.GitLab).load() halt

Observe que a primeira linha é deixada em branco de maneira intencional.

Como algumas configurações podem ser específicas do servidor, elas não são armazenadas no repositório, mas separadamente. Se o hook inicial for sempre o mesmo, você pode simplesmente armazená-lo no repositório.

gitlab-ci.yml

Agora, para a configuração da entrega contínua:

build image:
  stage: build
  tags:
    - test
  script:
    - cp -r /InterSystems/mount ci
    - cd ci
    - echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
    - mv temp.txt load_ci.script
    - cd ..
    - docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.domain.com/test/docker:$CI_COMMIT_REF_NAME .

O que está acontecendo aqui?

Primeiro, como o docker build pode acessar apenas subdiretórios de um diretório de compilação base — na raiz do repositório do nosso caso, precisamos copiar nosso diretório "secreto" (aquele com GitLab.xmliris.key, pwd.txt e load_ci.script) no repositório clonado.

Em seguida, o primeiro acesso ao terminal requer um usuário/senha, então nós os adicionamos a load_ci.script (por isso a linha vazia no início de load_ci.script).

Por fim, criamos a imagem do docker e a marcamos adequadamente: docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

onde $CI_COMMIT_REF_NAME é o nome de um branch atual. Observe que a primeira parte da tag de imagem deve ter o mesmo nome do nome do projeto no GitLab, para que possa ser vista na guia GitLab Registry (instruções sobre a marcação estão disponíveis na guia Registry).

Dockerfile

A criação da imagem docker é feita usando o Dockerfile:

FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0

ENV SRC_DIR=/tmp/src
ENV CI_DIR=$SRC_DIR/ci
ENV CI_PROJECT_DIR=$SRC_DIR

COPY ./ $SRC_DIR

RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt \
 && iris start $ISC_PACKAGE_INSTANCENAME \
 && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS &lt; $CI_DIR/load_ci.script \
 && iris stop $ISC_PACKAGE_INSTANCENAME quietly

Começamos a partir do contêiner básico iris.

Primeiro, copiamos nosso repositório (e diretório "secreto") dentro do contêiner.

Em seguida, copiamos a chave de licença e GitLab.xml para o diretório mgr.

Em seguida, alteramos a senha para o valor de pwd.txt. Observe que pwd.txt é excluído nessa operação.

Depois disso, a instância é iniciada e load_ci.script é executado.

Por fim, a instância iris é interrompida.

Veja o registro do job (parcial, os registros de carregamento/compilação foram ignorados):

Running with gitlab-runner 10.6.0 (a3543a27)
  on docker 7b21e0c4
Using Shell executor...
Running on docker...
Fetching changes...
Removing ci/
Removing temp.txt
HEAD is now at 5ef9904 Build load_ci.script
From http://gitlab.eduard.win/test/docker
   5ef9904..9753a8d  master     -> origin/master
Checking out 9753a8db as master...
Skipping Git submodules setup
$ cp -r /InterSystems/mount ci
$ cd ci
$ echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
$ mv temp.txt load_ci.script
$ cd ..
$ docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.eduard.win/test/docker:$CI_COMMIT_REF_NAME .
Sending build context to Docker daemon  401.4kB

Step 1/6 : FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0
 ---> cd2e53e7f850
Step 2/6 : ENV SRC_DIR=/tmp/src
 ---> Using cache
 ---> 68ba1cb00aff
Step 3/6 : ENV CI_DIR=$SRC_DIR/ci
 ---> Using cache
 ---> 6784c34a9ee6
Step 4/6 : ENV CI_PROJECT_DIR=$SRC_DIR
 ---> Using cache
 ---> 3757fa88a28a
Step 5/6 : COPY ./ $SRC_DIR
 ---> 5515e13741b0
Step 6/6 : RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/  && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/  && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt  && iris start $ISC_PACKAGE_INSTANCENAME  && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS &lt; $CI_DIR/load_ci.script  && iris stop $ISC_PACKAGE_INSTANCENAME quietly
 ---> Running in 86526183cf7c
.
Waited 1 seconds for InterSystems IRIS to start
This copy of InterSystems IRIS has been licensed for use exclusively by:
ISC Internal Container Sharding
Copyright (c) 1986-2018 by InterSystems Corporation
Any other use is a violation of your license agreement

%SYS>
1

%SYS>
Using 'iris.cpf' configuration file

This copy of InterSystems IRIS has been licensed for use exclusively by:
ISC Internal Container Sharding
Copyright (c) 1986-2018 by InterSystems Corporation
Any other use is a violation of your license agreement

1 alert(s) during startup. See messages.log for details.
Starting IRIS

Node: 39702b122ab6, Instance: IRIS

Username:
Password:

Load started on 04/06/2018 17:38:21
Loading file /usr/irissys/mgr/GitLab.xml as xml
Load finished successfully.

USER>

USER>

[2018-04-06 17:38:22.017] Running init hooks: before

[2018-04-06 17:38:22.017] Importing hooks dir /tmp/src/MyApp/Hooks/

[2018-04-06 17:38:22.374] Executing hook class: MyApp.Hooks.Global

[2018-04-06 17:38:22.375] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.375] Importing dir /tmp/src/

Loading file /tmp/src/MyApp/Tests/TestSuite.cls as udl

Compilation started on 04/06/2018 17:38:22 with qualifiers 'c'
Compilation finished successfully in 0.194s.

Load finished successfully.

[2018-04-06 17:38:22.876] Running init hooks: after

[2018-04-06 17:38:22.878] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.921] Executing hook class: MyApp.Hooks.Global
Removing intermediate container 39702b122ab6
 ---> dea6b2123165
[Warning] One or more build-args [CI_PROJECT_DIR] were not consumed
Successfully built dea6b2123165
Successfully tagged docker.domain.com/test/docker:master
Job succeeded

Estou usando o executor GitLab Shell, e não o executor Docker. O executor Docker é usado quando você precisa de algo de dentro da imagem, por exemplo, você está criando um aplicativo Android em um contêiner java e precisa apenas de um apk. No nosso caso, precisamos de um contêiner inteiro e, para isso, precisamos do executor Shell. Então, estamos executando comandos do Docker pelo executor GitLab Shell.

 

Executar

Temos nossa imagem, agora vamos executá-la.  No caso de ramificações de recursos, podemos simplesmente destruir o contêiner antigo e iniciar o novo. No caso do ambiente, podemos executar um container temporário e substituir o contêiner do ambiente caso os testes tenham êxito (isso fica como um exercício para o leitor).

Aqui está o script.

destroy old:
  stage: destroy
  tags:
    - test
  script:
    - docker stop iris-$CI_COMMIT_REF_NAME || true
    - docker rm -f iris-$CI_COMMIT_REF_NAME || true

Esse script destrói o contêiner em execução no momento e é sempre bem-sucedido (por padrão, o docker falha se tentar parar/remover um contêiner inexistente).

Em seguida, iniciamos a nova imagem e a registramos como um ambiente. Contêiner Nginx faz proxy automático de solicitações usando a variável de ambiente VIRTUAL_HOST e a diretiva de exposição (para saber em qual porta fazer o proxy).

run image:
  stage: run
  environment:
    name: $CI_COMMIT_REF_NAME
    url: http://$CI_COMMIT_REF_SLUG. docker.domain.com/index.html
  tags:
    - test
  script:
    - docker run -d
      --expose 52773
      --env VIRTUAL_HOST=$CI_COMMIT_REF_SLUG.docker.eduard.win
      --name iris-$CI_COMMIT_REF_NAME
      docker.domain.com/test/docker:$CI_COMMIT_REF_NAME
      --log $ISC_PACKAGE_INSTALLDIR/mgr/messages.log

 

Testes

Vamos fazer alguns testes.

test image:
  stage: test
  tags:
    - test
  script:
    - docker exec iris-$CI_COMMIT_REF_NAME irissession iris -U USER "##class(isc.git.GitLab).test()"

Publicar

Por fim, vamos publicar nossa imagem no registro

publish image:
  stage: publish
  tags:
    - test
  script:
    - docker login docker.domain.com -u dev -p 123
    - docker push docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

O usuário/código pode ser transmitido usando variáveis secretas do GitLab.

Agora, podemos ver a imagem no GitLab:

E outros desenvolvedores podem a extrair do registro. Na guia de ambientes, todos os ambientes estão disponíveis para a fácil navegação:

 

Conclusão

Nessa série de artigos, discuti abordagens gerais de entrega contínua. É um tema extremamente vasto e essa série de artigos precisa ser vista mais como uma coleção de receitas do que algo definitivo. Se você deseja automatizar o desenvolvimento, os testes e a entrega do seu aplicativo, a entrega contínua em geral e o GitLab em particular é o melhor caminho. A entrega contínua e os contêineres permitem que você personalize seu fluxo de trabalho conforme necessário.

Links

O que vem a seguir

É isso. Espero que eu tenha abordado os conceitos básicos da entrega contínua e dos contêineres.

Há vários tópicos sobre os quais não falei (talvez mais tarde), especialmente em relação a contêineres:

  • Os dados podem ser persistentes fora do contêiner. Veja a documentação relacionada.
  • Plataformas de orquestração como kubernetes
  • InterSystems Cloud Manager
  • Gerenciamento de ambiente - criando ambientes temporários para testes, removendo ambientes antigos após a mesclagem de ramificações de recursos
  • Docker compose para implantações de vários contêineres
  • Diminuindo o tamanho da imagem docker e os tempos de construção
  • ...
0
0 157
Artigo Danusa Calixto · Dez. 22, 2022 10m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Git básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de trabalho do GitLab
  • Entrega contínua
  • Instalação e configuração do GitLab
  • CI/CD do GitLab

No primeiro artigo, abordamos os fundamentos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno e como o Git pode ser usado para desenvolver software.

No segundo artigo, abordamos o fluxo de trabalho do GitLab: um processo inteiro do ciclo de vida do software e a entrega contínua.

No terceiro artigo, abordamos a instalação e configuração do GitLab e a conexão dos seus ambientes a ele

Neste artigo, finalmente, vamos escrever uma configuração de CD.

Plano

Ambientes

Em primeiro lugar, precisamos de vários ambientes e branches que correspondam a eles:

EnvironmentBranchDeliveryWho can commitWho can merge
TestmasterAutomaticDevelopers  OwnersDevelopers  Owners
PreprodpreprodAutomaticNo oneOwners
ProdprodSemiautomatic (press button to deliver)No one

Owners

Ciclo de desenvolvimento

E, como exemplo, desenvolveremos um novo recurso usando o fluxo do GitLab e o entregaremos usando a CD do GitLab.

  1. O recurso é desenvolvido em um branch de recursos.
  2. O branch de recurso é revisado e mesclado no master branch.
  3. Depois de um tempo (vários recursos mesclados), o master é mesclado com o preprod
  4. Depois de um tempo (teste do usuário, etc.), o preprod é mesclado com o prod

Veja como isso ficaria (marquei as partes que precisamos desenvolver para o CD em itálico):

  1. Desenvolvimento e teste
    • O desenvolvedor envia o código para o novo recurso em um branch de recursos separado
    • Depois que o recurso se torna estável, o desenvolvedor mescla nosso branch de recursos no master branch
    • O código do branch master é entregue ao ambiente de teste, onde é carregado e testado
  2. Entrega para o ambiente de pré-produção
    • O desenvolvedor cria a solicitação de mesclagem do branch master para o branch de pré-produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O código do branch de pré-produção é entregue ao ambiente de pré-produção
  3. Entrega para o ambiente de produção
    • O desenvolvedor cria a solicitação de mesclagem do branch de pré-produção para o branch de produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O proprietário do repositório aperta o botão "Implantar"
    • O código do branch de produção é entregue ao ambiente de produção

Ou o mesmo, mas em formato de gráfico:

Aplicativo

Nosso aplicativo consiste em duas partes:

  • API REST desenvolvida na plataforma InterSystems
  • Web application de JavaScript cliente

Estágios

Com o plano acima, podemos determinar as etapas que precisamos definir na nossa configuração de entrega contínua:

  • Carregamento — para importar o código do lado do servidor para o InterSystems IRIS
  • Teste — para testar o código do servidor e cliente
  • Pacote — para criar o código do cliente
  • Implantação — para "publicar" o código do cliente usando o servidor web

Veja como isso fica no arquivo de configuração gitlab-ci.yml:

stages:
  - load
  - test
  - package
  - deploy

Scripts

Carregamento

Em seguida, vamos definir os scripts. Documentos de scripts. Primeiro, vamos definir um script load server que carrega o código do lado do servidor:

load server:
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test
  stage: load
  script: csession IRIS "##class(isc.git.GitLab).load()"

O que acontece aqui?

  • load server é o nome de um script
  • em seguida, descrevemos o ambiente em que esse script é executado
  • only: master — informa ao GitLab que esse script só deve ser executado quando houver um commit para o master branch
  • tags: test especifica que esse script só deve ser executado em um runner com a tag test
  • stage especifica o estágio para um script
  • script define o código para executar. No nosso caso, chamamos o classmethod load da classe isc.git.GitLab

Observação importante

Para InterSystems IRIS, troque csession por iris session.

Para Windows, use: irisdb -s ../mgr -U TEST "##class(isc.git.GitLab).load()

Agora, vamos escrever a classe isc.git.GitLab correspondente. Todos os pontos de entrada nessa classe ficam desta forma:

ClassMethod method()
{
    try {
        // code
        halt
    } catch ex {
        write !,$System.Status.GetErrorText(ex.AsStatus()),!
        do $system.Process.Terminate(, 1)
    }
}

Observe que esse método pode terminar de duas maneiras:

  • interrompendo o processo atual — que é registrado no GitLab como uma conclusão bem-sucedida
  • chamando $system.Process.Terminate — que termina o processo de maneira anormal e o GitLab registra isso como um erro

Dito isso, aqui está nosso código de carregamento:

/// Do a full load
/// do ##class(isc.git.GitLab).load()
ClassMethod load()
{
    try {
        set dir = ..getDir()
        do ..log("Importing dir " _ dir)
        do $system.OBJ.ImportDir(dir, ..getExtWildcard(), "c", .errors, 1)
        throw:$get(errors,0)'=0 ##class(%Exception.General).%New("Load error")

        halt
    } catch ex {
        write !,$System.Status.GetErrorText(ex.AsStatus()),!
        do $system.Process.Terminate(, 1)
    }
}

Dois métodos de utilitários são chamados:

  • getExtWildcard — para obter uma lista das extensões de arquivo relevantes
  • getDir — para obter o diretório do repositório

Como podemos obter o diretório?

Quando o GitLab executa um script, primeiro, ele especifica várias variáveis de ambiente. Uma delas é a CI_PROJECT_DIR — o caminho completo onde o repositório é clonado e onde o job é executado. Ele pode ser obtido facilmente no nosso método getDir :

ClassMethod getDir() [ CodeMode = expression ]
{
##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR"))
}

####Testes

Aqui está o script de teste:

load test:
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test
  stage: test
  script: csession IRIS "##class(isc.git.GitLab).test()"
  artifacts:
    paths:
      - tests.html

O que mudou? O nome e o código do script, é claro, mas o artefato também foi adicionado. Um artefato é uma lista de arquivos e diretórios que são anexados a um job depois que ele é concluído com sucesso. No nosso caso, depois que os testes forem concluídos, podemos gerar a página HTML redirecionando para os resultados dos testes e disponibilizá-la a partir do GitLab. 

Observe que há bastante copiar e colar do estágio de carregamento — o ambiente é o mesmo, partes do script, como ambientes, podem ser rotuladas separadamente e anexadas a um script. Vamos definir o ambiente de teste:

.env_test: &env_test
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test

Agora, nosso script de teste fica assim:

load test:
  <<: *env_test
  script: csession IRIS "##class(isc.git.GitLab).test()"
  artifacts:
    paths:
      - tests.html

Em seguida, vamos executar os testes usando o framework UnitTest.

/// do ##class(isc.git.GitLab).test()
ClassMethod test()
{
    try {
        set tests = ##class(isc.git.Settings).getSetting("tests")
        if (tests'="") {
            set dir = ..getDir()
            set ^UnitTestRoot = dir

            $$$TOE(sc, ##class(%UnitTest.Manager).RunTest(tests, "/nodelete"))
            $$$TOE(sc, ..writeTestHTML())
            throw:'..isLastTestOk() ##class(%Exception.General).%New("Tests error")
        }
        halt
    } catch ex {
        do ..logException(ex)
        do $system.Process.Terminate(, 1)
    }
}

A definição do teste, nesse caso, é um caminho relativo à raiz do repositório onde os testes de unidade são armazenados. Se estiver vazio, pulamos testes. O método writeTestHTML é usado para gerar o html com um redirecionamento para os resultados dos testes:

ClassMethod writeTestHTML()
{
    set text = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), "html").Data.Read()
    set text = $replace(text, "!!!", ..getURL())
    
    set file = ##class(%Stream.FileCharacter).%New()
    set name = ..getDir() _  "tests.html"
    do file.LinkToFile(name)
    do file.Write(text)
    quit file.%Save()
}

ClassMethod getURL()
{
    set url = ##class(isc.git.Settings).getSetting("url")
    set url = url _ $system.CSP.GetDefaultApp("%SYS")
    set url = url_"/%25UnitTest.Portal.Indices.cls?Index="_ $g(^UnitTest.Result, 1) _ "&$NAMESPACE=" _ $zconvert($namespace,"O","URL")
    quit url
}

ClassMethod isLastTestOk() As %Boolean
{
    set in = ##class(%UnitTest.Result.TestInstance).%OpenId(^UnitTest.Result)
    for i=1:1:in.TestSuites.Count() {
        #dim suite As %UnitTest.Result.TestSuite
        set suite = in.TestSuites.GetAt(i)
        return:suite.Status=0 $$$NO
    }
    quit $$$YES
}

XData html
{
<html lang="en-US">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="refresh" content="0; url=!!!"/>
<script type="text/javascript">
window.location.href = "!!!"
</script>
</head>
<body>
If you are not redirected automatically, follow this <a href='!!!'>link to tests</a>.
</body>
</html>
}

Pacote

Nosso cliente é uma página HTML simples:

<html>
<head>
<script type="text/javascript">
function initializePage() {
  var xhr = new XMLHttpRequest();
  var url = "${CI_ENVIRONMENT_URL}:57772/MyApp/version";
  xhr.open("GET", url, true);
  xhr.send();
  xhr.onloadend = function (data) {
    document.getElementById("version").innerHTML = "Version: " + this.response;
  };
  
  var xhr = new XMLHttpRequest();
  var url = "${CI_ENVIRONMENT_URL}:57772/MyApp/author";
  xhr.open("GET", url, true);
  xhr.send();
  xhr.onloadend = function (data) {
    document.getElementById("author").innerHTML = "Author: " + this.response;
  };
}
</script>
</head>
<body  onload="initializePage()">
<div id = "version"></div>
<div id = "author"></div>
</body>
</html>

E, para criá-la, precisamos substituir ${CI_ENVIRONMENT_URL} pelo seu valor. Claro, um aplicativo real provavelmente exigiria npm, mas esse é apenas um exemplo. Aqui está o script:

package client:
  <<: *env_test
  stage: package
  script: envsubst < client/index.html > index.html
  artifacts:
    paths:
      - index.html

Implantação

Por fim, implantamos nosso cliente ao copiar index.html para o diretório raiz do servidor web.

deploy client:
  <<: *env_test
  stage: deploy
  script: cp -f index.html /var/www/html/index.html

É isso!

Vários ambientes

O que fazer se você precisar executar o mesmo script (semelhante) em vários ambientes? Partes do script também podem ser rótulos, então aqui está uma configuração de exemplo que carrega o código em ambientes de teste e pré-produção:

stages:
  - load
  - test

.env_test: &env_test
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test
    
.env_preprod: &env_preprod
  environment:
    name: preprod
    url: http://preprod.hostname.com
  only:
    - preprod
  tags:
    - preprod

.script_load: &script_load
  stage: load
  script: csession IRIS "##class(isc.git.GitLab).loadDiff()"

load test:
  <<: *env_test
  <<: *script_load

load preprod:
  <<: *env_preprod
  <<: *script_load

Assim, podemos fugir de copiar e colar o código.

Veja a configuração de CD completa aqui. Ela segue o plano original de mover código entre os ambientes de teste, pré-produção e produção.

Conclusão

A entrega contínua pode ser configurada para automatizar qualquer fluxo de trabalho de desenvolvimento necessário.

Links

O que vem a seguir

No próximo artigo, vamos criar a configuração de CD que usa o contêiner Docker do InterSystems IRIS.

0
0 101
Artigo Danusa Calixto · Dez. 15, 2022 5m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Git básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de trabalho do GitLab
  • Entrega contínua
  • Instalação e configuração do GitLab
  • CI/CD do GitLab

No primeiro artigo, abordamos os fundamentos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno e como o Git pode ser usado para desenvolver software.

No segundo artigo, abordamos o fluxo de trabalho do GitLab: um processo inteiro do ciclo de vida do software e a entrega contínua.

Neste artigo, vamos discutir:

  • Instalação e configuração do GitLab
  • Conexão dos seus ambientes ao GitLab

Instalação do GitLab

Vamos instalar o GitLab no local. Há várias maneiras de instalar o GitLab — da fonte, pacote, em um contêiner. Não descreverei todos os passos aqui, há um guia para isso. Ainda assim, algumas observações.

Pré-requisitos:

  • Servidor separado — como é um web application e um recurso bastante intensivo, é melhor executar em um servidor separado
  • Linux
  • (Opcional, mas altamente recomendável) Domínio — necessário para executar páginas e proteger a configuração inteira

Configuração

Primeiro de tudo, você provavelmente precisa enviar e-mails com notificações.

Em seguida, recomendo instalar Páginas. Como discutido no artigo anterior — artefatos do script podem ser enviados para o GitLab. O usuário pode fazer o download deles, mas é útil poder abri-los diretamente no navegador e, para isso, precisamos de páginas.

Por que você precisa de páginas:

Como as páginas html podem ter um redirecionamento onload, elas podem ser usadas para enviar o usuário para onde precisamos. Por exemplo, veja este código que gera uma página html que envia um usuário para o último teste de unidade executado (no momento da geração do html):

ClassMethod writeTestHTML()
{
  set text = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), "html").Data.Read()
  set text = $replace(text, "!!!", ..getURL())
  
  set file = ##class(%Stream.FileCharacter).%New()
  set name = "tests.html"
  do file.LinkToFile(name)
  do file.Write(text)
  quit file.%Save()
}

ClassMethod getURL()
{
  set url = "http://host:57772"
  set url = url _ $system.CSP.GetDefaultApp("%SYS")
  set url = url_"/%25UnitTest.Portal.Indices.cls?Index="_ $g(^UnitTest.Result, 1) _ "&$NAMESPACE=" _ $zconvert($namespace,"O","URL")
  quit url
}

XData html
{

  
  
    If you are not redirected automatically, follow this link to tests.
  

}

Encontrei um bug usando as páginas (erro 502 ao procurar artefatos), veja aqui a correção.

 

Conexão dos seus ambientes ao GitLab

Para executar scripts de CD, você precisa de ambientes, servidores configurados para executar seu aplicativo. Presumindo que você tem um servidor Linux com o produto InterSystems instalado (digamos InterSystems IRIS, mas funciona também com o Caché e Ensemble), estas etapas conectam o ambiente ao GitLab:

  1. Instalar o runner do GitLab
  2. Registrar o runner com o GitLab
  3. Permitir que o runner chame o InterSystems IRIS

Observação importante sobre a instalação do runner GitLab, NÃO clone servidores após instalar o runner do GitLab.  Os resultados são imprevisíveis e muito indesejados.

Registrar o runner com o GitLab

Após executar o inicial:

sudo gitlab-runner register

você verá vários prompts e, embora a maioria das etapas seja bastante direta, várias não são:

Insira o token gitlab-ci para este runner

Há vários tokens disponíveis:

  • Um para o sistema inteiro (disponível nas configurações de administração)
  • Um para cada projeto (disponível nas configurações do projeto)

Conforme você conecta um runner para executar a CD para um projeto específico, você precisa especificar um token para este projeto.

Insira as tags gitlab-ci para este runner (separadas por vírgulas):

Na configuração de CD, você pode filtrar quais scripts vão ser executados em quais tags. Então, no caso mais simples, especifique uma tag, que seria o nome do ambiente.

Insira o executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
docker

Se você estiver usando o servidor habitual sem docker, escolha shell.  O Docker será discutido nas partes posteriores.

Permitir que o runner chame o InterSystems IRIS

Depois de conectar o runner ao GitLab, precisamos permitir que ele interaja com o InterSystems IRIS, para isso:

  1. O usuário gitlab-runner precisa conseguir chamar csession. Para fazer isso, adicione-o ao grupo cacheusr: 
    • usermod -a -G cacheusr gitlab-runner
  2. Crie o usuário gitlab-runner no InterSystems IRIS e dê a ele funções para realizar tarefas de CD (escreva para DB, etc.)
  3. Permitir a autenticação no nível do SO

Para 2 e 3, outras abordagens podem ser usadas, como a transmissão de usuário/código, mas acho que a autenticação de SO é preferível. 

Conclusão

Nesta parte:

  • GitLab instalado
  • Ambientes conectados ao GitLab

O que vem a seguir

Na próxima parte, escrevemos nossa configuração de entrega contínua.

0
0 156
Artigo Danusa Calixto · Nov. 9, 2022 10m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Git básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de trabalho do GitLab
  • Entrega contínua
  • Instalação e configuração do GitLab
  • CI/CD do GitLab

No artigo anterior, abordamos os fundamentos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno e como o Git pode ser usado para desenvolver software. Ainda assim, nosso foco foi na parte da implementação do desenvolvimento de software, mas esta parte apresenta:

  • Fluxo de trabalho do GitLab — um processo completo do ciclo de vida do software, desde a ideia até o feedback do usuário
  • Entrega Contínua — uma abordagem de engenharia de software em que as equipes produzem software em ciclos curtos, garantindo que o software possa ser lançado de forma confiável a qualquer momento. Seu objetivo é construir, testar e lançar software com mais rapidez e frequência.

Fluxo de trabalho do GitLab

O fluxo de trabalho do GitLab é uma sequência lógica de possíveis ações a serem tomadas durante todo o ciclo de vida do processo de desenvolvimento de software.

O fluxo de trabalho do GitLab leva em consideração o fluxo do GitLab, que discutimos em um artigo anterior. Veja como funciona:

  1. Ideia: todas as novas propostas começam com uma ideia.
  2. Problema: a maneira mais eficaz de discutir uma ideia é criar um problema para ela. Sua equipe e seus colaboradores podem ajudar você a aprimorar e melhorar a ideia no rastreador de problemas.
  3. Plano: quando a discussão chega a um acordo, é hora de programar. Porém, primeiro, precisamos priorizar e organizar nosso fluxo de trabalho ao atribuir problemas a marcos e quadro de problemas.
  4. Código: agora estamos prontos para escrever nosso código, já que está tudo organizado.
  5. Commit: depois de satisfeitos com o rascunho, podemos enviar nosso código para um feature-branch com controle de versão. O fluxo do GitLab foi explicado em detalhes no artigo anterior.
  6. Teste: executamos nossos scripts usando o CI GitLab, para construir e testar nosso aplicativo.
  7. Revisão: assim que nosso script funcionar e nossos testes e compilações forem bem-sucedidos, estamos prontos para que nosso código seja revisado e aprovado.
  8. Staging: agora é hora de implantar nosso código em um ambiente de staging para verificar se tudo funciona como esperado ou se ainda precisamos de ajustes.
  9. Produção: quando tudo estiver funcionando como deve, é hora de implantar no nosso ambiente de produção!
  10. Feedback: agora é hora de olhar para trás e verificar qual etapa do nosso trabalho precisa ser melhorada.

Novamente, o processo em si não é novo (ou exclusivo do GitLab) e pode ser alcançado com outras ferramentas da sua escolha.

Vamos discutir várias dessas etapas e o que elas implicam. Também há documentação disponível.

Problema e plano

As etapas iniciais do fluxo de trabalho do GitLab são centradas em um problema: um recurso, bug ou outro tipo de trabalho semanticamente separado.

O problema tem várias finalidades, como:

  • Gerenciamento: um problema tem data de vencimento, pessoa designada, tempo gasto e estimativas, etc. para ajudar a monitorar a resolução do problema.
  • Administrativo: um problema faz parte de um marco, quadro kanban, que nos permite rastrear nosso software à medida que ele avança de versão para versão.
  • Desenvolvimento: um problema tem uma discussão e commits associados a ele.

A etapa de planejamento nos permite agrupar os problemas por prioridade, marco, quadro kanban e ter uma visão geral disso.

O desenvolvimento foi discutido na parte anterior, basta seguir qualquer fluxo git que quiser. Depois que desenvolvemos nosso novo recurso e o mesclamos no master: o que vem depois?

Entrega contínua

A entrega contínua é uma abordagem de engenharia de software em que as equipes produzem software em ciclos curtos, garantindo que o software possa ser lançado de forma confiável a qualquer momento. Seu objetivo é construir, testar e lançar software com mais rapidez e frequência. A abordagem ajuda a reduzir o custo, o tempo e o risco da entrega de alterações, permitindo mais atualizações incrementais para aplicativos em produção. Um processo de implantação simples e repetível é importante para a entrega contínua.

Entrega contínua no GitLab

No GitLab, a configuração da entrega contínua é definida por repositório como um arquivo de configuração YAML.

  • A configuração de entrega contínua é uma série de estágios consecutivos.
  • Cada estágio tem um ou vários scripts que são executados em paralelo.

O script define uma ação e quais condições devem ser atendidas para executá-la:

  • O que fazer (executar o comando do SO, executar um contêiner)?
  • Quando executar o script:
    • Quais são os gatilhos (commit de um branch específico)?
    • Nós o executamos se os estágios anteriores falharam?
  • Executar manualmente ou automaticamente?
  • Em que ambiente executar o script?
  • Quais artefatos salvar após a execução dos scripts (eles são carregados do ambiente para o GitLab para facilitar o acesso)?

Ambiente - é um servidor ou contêiner configurado no qual você pode executar seus scripts.

Runners executam scripts em ambientes específicos. Eles são conectados ao GitLab e executam scripts conforme necessário.

O runner pode ser implantado em um servidor, contêiner ou até mesmo na sua máquina local.

Como acontece a entrega contínua?

  1. O novo commit é enviado para o repositório.
  2. O GitLab verifica a configuração de entrega contínua.
  3. A configuração de entrega contínua contém todos os scripts possíveis para todos os casos, para que sejam filtrados para um conjunto de scripts que devem ser executados para esse commit específico (por exemplo, um commit para o branch master aciona apenas ações relacionadas a um branch master). Esse conjunto é chamado de pipeline.
  4. O pipeline é executado em um ambiente de destino e os resultados da execução são salvos e exibidos no GitLab.

Por exemplo, aqui está um pipeline executado após um commit em um branch master:

Ele consiste em quatro etapas, executadas consecutivamente

  1. O estágio de carregamento carrega o código em um servidor
  2. O estágio de teste executa testes de unidade
  3. O estágio de pacote consiste em dois scripts executados em paralelo:
    • Compilação cliente
    • Código de exportação do servidor (principalmente para fins informativos)
  4. O estágio de implantação move o cliente criado para o diretório do servidor web.

Como podemos ver, todos os scripts foram executados com sucesso. Se um dos scripts falhar, por padrão, os scripts posteriores não são executados (mas podemos alterar esse comportamento):

Se abrirmos o script, podemos ver o log e determinar por que ele falhou:

Running with gitlab-runner 10.4.0 (857480b6)
 on test runner (ab34a8c5)
Using Shell executor...
Running on gitlab-test...
&lt;span class="term-fg-l-green term-bold">Fetching changes...&lt;/span>
Removing diff.xml
Removing full.xml
Removing index.html
Removing tests.html
HEAD is now at a5bf3e8 Merge branch '4-versiya-1-0' into 'master'
From http://gitlab.eduard.win/test/testProject
 * [new branch] 5-versiya-1-1 -> origin/5-versiya-1-1
 a5bf3e8..442a4db master -> origin/master
 d28295a..42a10aa preprod -> origin/preprod
 3ac4b21..7edf7f4 prod -> origin/prod
&lt;span class="term-fg-l-green term-bold">Checking out 442a4db1 as master...&lt;/span>
&lt;span class="term-fg-l-green term-bold">Skipping Git submodules setup&lt;/span>
&lt;span class="term-fg-l-green term-bold">$ csession ensemble "##class(isc.git.GitLab).loadDiff()"&lt;/span>

[2018-03-06 13:58:19.188] Importing dir /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/

[2018-03-06 13:58:19.188] Loading diff between a5bf3e8596d842c5cc3da7819409ed81e62c31e3 and 442a4db170aa58f2129e5889a4bb79261aa0cad0

[2018-03-06 13:58:19.192] Variable modified
var=$lb("MyApp/Info.cls")

Load started on 03/06/2018 13:58:19
Loading file /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/MyApp/Info.cls as udl
Load finished successfully.

[2018-03-06 13:58:19.241] Variable items
var="MyApp.Info.cls"
var("MyApp.Info.cls")=""

Compilation started on 03/06/2018 13:58:19 with qualifiers 'cuk /checkuptodate=expandedonly'
Compiling class MyApp.Info
Compiling routine MyApp.Info.1
ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1]
 TEXT:  quit, "1.0" }
Detected 1 errors during compilation in 0.010s.

[2018-03-06 13:58:19.252] ERROR #5475: Error compiling routine: MyApp.Info.1. Errors: ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1]
 > ERROR #5030: An error occurred while compiling class 'MyApp.Info'
&lt;span class="term-fg-l-red term-bold">ERROR: Job failed: exit status 1
&lt;/span>

O erro de compilação causou a falha do nosso script.

Conclusão

  • O GitLab é compatível com todos os principais estágios de desenvolvimento de software.
  • A entrega contínua pode ajudar você a automatizar tarefas de construção, teste e implantação do seu software.

O que vem a seguir?

No próximo artigo, vamos:

  • Instalar o GitLab.
  • Conectá-lo a diversos ambientes com os produtos InterSystems instalados.
  • Escrever uma configuração de entrega contínua.

Vamos discutir como a entrega contínua deve funcionar.

Em primeiro lugar, precisamos de vários ambientes e branches que correspondam a eles. O código entra nesse branch e é entregue ao ambiente de destino:

AmbienteBranchEntregaQuem pode fazer enviosQuem pode mesclar
TestemasterAutomáticoDesenvolvedores  ProprietáriosDesenvolvedores  Proprietários
PreprodpreprodAutomáticoNinguémProprietários
ProdprodSemiautomático (pressionar botão para entregar)NinguémProprietários

E, como exemplo, desenvolveremos um novo recurso usando o fluxo do GitLab e o entregaremos usando a CD do GitLab.

  1. O recurso é desenvolvido em um branch de recursos.
  2. O branch de recurso é revisado e mesclado no master branch.
  3. Depois de um tempo (vários recursos mesclados), o master é mesclado com o preprod
  4. Depois de um tempo (teste do usuário, etc.), o preprod é mesclado com o prod

Veja como ficaria:

  1. Desenvolvimento e teste
    • O desenvolvedor envia o código para o novo recurso em um branch de recursos separado
    • Depois que o recurso se torna estável, o desenvolvedor mescla nosso branch de recursos no master branch
    • O código do branch master é entregue ao ambiente de teste, onde é carregado e testado
  2. Entrega para o ambiente de pré-produção
    • O desenvolvedor cria a solicitação de mesclagem do branch master para o branch de pré-produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O código do branch de pré-produção é entregue ao ambiente de pré-produção
  3. Entrega para o ambiente de produção
    • O desenvolvedor cria a solicitação de mesclagem do branch de pré-produção para o branch de produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O proprietário do repositório aperta o botão "Implantar"
    • O código do branch de produção é entregue ao ambiente de produção

Ou o mesmo, mas em formato gráfico:

 

0
0 302
Artigo Eduard Lebedyuk · Nov. 22, 2021 8m read

Todo mundo tem um ambiente de teste.

Algumas pessoas têm a sorte de ter um ambiente totalmente separado para executar a produção.

-- Desconhecido

.

Nesta série de artigos, gostaria de apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com as tecnologias InterSystems e GitLab. Vou cobrir tópicos como:

  • Git Básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de Trabalho do GitLab
  • GitLab CI/CD
  • CI/CD com contêineres

Esta primeira parte trata do pilar do desenvolvimento de software moderno - sistema de controle de versão Git e vários fluxos Git.

Git Básico

Embora o tópico principal que iremos discutir seja o desenvolvimento de software em geral e como o GitLab pode nos capacitar nesse esforço, o Git, ou melhor, os vários conceitos de alto nível subjacentes no design do Git, são importantes para o melhor entendimento de conceitos posteriores.

Dito isso, o Git é um sistema de controle de versão, baseado nessas ideias (existem muitas outras, essas são as mais importantes):

  • Desenvolvimento não linear significa que enquanto nosso software é lançado consequentemente da versão 1 para a 2 para a 3, sob a mesa a mudança da versão 1 para a 2 é feita em paralelo - vários desenvolvedores desenvolvem uma série de recursos/correções de bugs simultaneamente.
  • Desenvolvimento distribuído significa que o desenvolvedor é independente de um servidor central ou de outros desenvolvedores e pode desenvolver facilmente em seu próprio ambiente.
  • Fusão - as duas ideias anteriores nos levam à situação em que muitas versões diferentes da verdade existem simultaneamente e precisamos uni-las de volta em um estado completo.

Agora, não estou dizendo que Git inventou esses conceitos. Não. Em vez disso, o Git os tornou fáceis e populares e isso, juntamente com várias inovações relacionadas, ou seja,  infraestrutura como código/conteinerização mudou o desenvolvimento de software.

Termos básicos do Git

Repositório é um projeto que armazena dados e metainformações sobre os dados.

  • O repositório "físico" é um diretório em um disco.
  • O repositório armazena arquivos e diretórios.
  • O repositório também armazena um histórico completo de alterações para cada arquivo.

O repositório pode ser armazenado:

  • Localmente, em seu próprio computador
  • Remotamente em um servidor remoto

Mas não há nenhuma diferença particular entre repositórios locais e remotos do ponto de vista do git.

Commit é um estado fixo do repositório. Obviamente, se cada commit armazenasse o estado completo do repositório, nosso repositório cresceria muito rapidamente. É por isso que um commit armazena um diff que é uma diferença entre o commit atual e seu commit pai.

Commits diferentes podem ter um número diferente de pais:

  • 0 - o primeiro commit no repositório não tem pais.
  • 1 - conforme o habitual - nosso commit mudou algo no repositório como era durante o commit pai
  • 2 - quando temos dois estados diferentes do repositório, podemos uni-los em um novo estado. E esse estado e esse commit teriam 2 pais.
  • 2 - pode acontecer quando unimos mais de 2 estados diferentes do repositório em um novo estado. Não seria particularmente relevante para nossa discussão, mas existe.

Agora, para um pai, cada commit diferente é chamado de commit filho. Cada commit pai pode ter qualquer número de commits filhos.

Branch é uma referência (ou ponteiro) para um commit.  Veja como funciona:

Nesta imagem, podemos ver o repositório com dois commits (círculos cinza), o segundo é o head do branch master. Depois de adicionar mais commits, nosso repositório começa a ficar assim:

Esse é o caso mais simples. Um desenvolvedor trabalha em uma mudança de cada vez. No entanto, normalmente, existem muitos desenvolvedores trabalhando simultaneamente em diferentes recursos e precisamos de uma árvore de commit para mostrar o que está acontecendo em nosso repositório.

Árvore de commit

Vamos começar do mesmo ponto de partida. Aqui está o repositório com dois commits:

Mas agora, dois desenvolvedores estão trabalhando ao mesmo tempo e para não interferir um no outro, eles trabalham em branches separados:

Depois de um tempo, eles precisam unir as alterações feitas e para isso eles criam uma solicitação de mesclagem (merge) (também chamada de pull request) - que é exatamente o que parece - é uma solicitação para unir dois estados diferentes do repositório (no nosso caso, queremos mesclar o develop branch no master branch) em um novo estado. Depois de ser devidamente revisado e aprovado, nosso repositório fica assim:

E o desenvolvimento continua:

Resumo - Git Básico

Conceitos principais:

  • Git é um sistema de controle de versão distribuído não linear.
  • Repositório armazena dados e metainformações sobre os dados.
  • Commit é um estado fixo do repositório.
  • Branch é uma referência para um commit. 
  • Solicitação de mesclagem (também chamada de pull request) - é uma solicitação para unir dois estados diferentes do repositório em um novo estado.

Se você quiser ler mais sobre o Git, existem livros disponíveis.

Fluxos Git

Agora que o leitor está familiarizado com os termos e conceitos básicos do Git, vamos falar sobre como a parte do desenvolvimento do ciclo de vida do software pode ser gerenciada usando o Git.  Existem várias práticas (chamadas  de fluxos) que descrevem o processo de desenvolvimento usando Git, mas vamos falar sobre duas delas:

  • Fluxo do GitHub
  • Fluxo do GitLab

Fluxo do GitHub

O fluxo do GitHub é tão fácil quanto parece. Aqui está:

  1. Crie um branch (ramificação) do repositório.
  2. Commit suas alterações para seu novo branch
  3. Envie um pull request do seu branch com as alterações propostas para iniciar uma discussão.
  4. Commit mais alterações em seu branch conforme necessário. Seu pull request será atualizado automaticamente.
  5. Mescle o pull request assim que o branch estiver pronto para ser mesclado.

E existem várias regras que devemos seguir:

  • master branch é sempre implantável (e funcionando!)

  • Não há desenvolvimento indo diretamente para o master branch

  • O desenvolvimento está acontecendo nos branches de recursos

  • master == ambiente** de produção*

  • Você precisa implantar na produção o mais rápido possível

    • Não confunda com "Produções Ensemble", aqui "Produção" significa SISTEMA EM PRODUÇÃO.

** Ambiente é um local configurado onde seu código é executado - pode ser um servidor, uma VM, até mesmo um contêiner.

Veja como funciona:

Você pode ler mais sobre o fluxo do GitHub aqui. Também há um guia ilustrado.

O fluxo do GitHub é bom para pequenos projetos e para testes se você está começando com os fluxos do Git. No entanto, o GitHub o usa, portanto, também pode ser viável em projetos grandes.

Fluxo do GitLab

Se você não estiver pronto para implantar na produção imediatamente, o fluxo do GitLab oferece um fluxo do GitHub + ambientes. É assim que funciona - você desenvolve em branches de recursos, como acima, mescla (merge) no master, como acima, mas aqui está uma diferença: o master é igual apenas no ambiente de teste. Além disso, você tem "Branches de ambiente" que estão vinculados a vários outros ambientes que você possa ter.

Normalmente, existem três ambientes (você pode criar mais se precisar):

  • Ambiente de teste == master branch
  • Ambiente de pré-produção == preprod branch
  • Ambiente de produção == prod branch

O código que chega em um dos branches do ambiente deve ser movido para o ambiente correspondente imediatamente, isso pode ser feito:

  • Automaticamente (cobriremos isso nas partes 2 e 3)
  • Parcialmente automático (igual ao automaticamente, exceto que um botão que autoriza a implantação deve ser pressionado)
  • Manualmente

Todo o processo é assim:

  1. O recurso é desenvolvido no branch de recursos.
  2. O branch de recurso é revisado e mesclado no master branch.
  3. Depois de um tempo (vários recursos mesclados), o master é mesclado com o preprod
  4. Depois de um tempo (teste do usuário, etc.), o preprod é mesclado com o prod  
  5. Enquanto estávamos mesclando e testando, vários novos recursos foram desenvolvidos e mesclados no master, então vá para parte 3.

Veja como funciona:

Você pode ler mais sobre o fluxo do GitLab aqui.

Conclusão

  • Git ****é um sistema de controle de versão distribuído não linear.
  • O fluxo Git pode ser usado como uma diretriz para o ciclo de desenvolvimento de software; existem vários que você pode escolher.

Links

Questões para discussão

  • Você usa um fluxo git? Qual?
  • Quantos ambientes você tem para um projeto padrão?

O que vem a seguir

Na próxima parte, iremos:

  • Instalar o GitLab.
  • Falar sobre alguns ajustes recomendados.
  • Discutir o fluxo de trabalho do GitLab (não deve ser confundido com o fluxo do GitLab).

Fique ligado.

0
0 311
Anúncio Timothy Leavitt · Out. 28, 2021

Eu gostaria de chamar a atenção de vocês ára duas sessões do Virtual Summit, mesmo elas não sendo tão legais quanto a Embedded Python.

Git & GitLab for Shared Development Environments detalha o recém lançado pacote git-source-control  (veja também no Open Exchange) que disponibiliza uma nova solução de ponta para integração IRIS/Git no lado servidor, especialmente para ambientes de desenvolvimento remotos compartilhados. (Eu preciso escrever uma postagem especifica sobre este pacote e planejo fazê-lo em breve.)

0
0 85
Artigo Evgeny Shvarov · Out. 6, 2020 13m read

Olá, desenvolvedores!

Muitos de vocês publicam suas bibliotecas InterSystems ObjectScript no Open Exchange e GitHub.

Mas o que você faz para facilitar o uso e a colaboração do seu projeto por desenvolvedores?

Neste artigo, quero apresentar uma maneira fácil de iniciar e contribuir com qualquer projeto ObjectScript apenas copiando um conjunto padrão de arquivos para o seu repositório.

Vamos lá!

Copie esses arquivos deste repositório para o seu repositório:

Dockerfile

docker-compose.yml

Installer.cls

iris.script

settings.json{#9f423fcac90bf80939d78b509e9c2dd2-d165a4a3719c56158cd42a4899e791c99338ce73}

.dockerignore{#f7c5b4068637e2def526f9bbc7200c4e-c292b730421792d809e51f096c25eb859f53b637}
.gitattributes{#fc723d30b02a4cca7a534518111c1a66-051218936162e5338d54836895e0b651e57973e1}
.gitignore{#a084b794bc0759e7a6b77810e01874f2-e6aff5167df2097c253736b40468e7b21e577eeb}

E você agora possui uma maneira padrão de lançar e colaborar com seu projeto. Abaixo está o longo artigo sobre como e por que isso funciona.

OBS.: Neste artigo, consideraremos projetos que podem ser executados no InterSystems IRIS 2019.1 e versões mais recentes.

Escolhendo o ambiente de lançamento para projetos do InterSystems IRIS

Normalmente, queremos que um desenvolvedor teste o projeto/biblioteca e tenha certeza de que será um exercício rápido e seguro.

Na minha humilde opinião, a abordagem ideal para lançar qualquer coisa nova de forma rápida e segura é através da utilização do contêiner Docker, que dá ao desenvolvedor uma garantia de que tudo o que ele/ela inicia, importa, compila e calcula é seguro para a máquina host e de que nenhum sistema ou código será destruído ou deteriorado. Se algo der errado, basta parar e remover o contêiner. Se a aplicação ocupa uma quantidade enorme de espaço em disco, você a limpa com o contêiner e seu espaço estará de volta. Se uma aplicação deteriora a configuração do banco de dados, você exclui apenas o contêiner com configuração deteriorada. É assim, simples e seguro.

O contêiner Docker oferece segurança e padronização.

A maneira mais simples de executar o contêiner Docker do InterSystems IRIS é executar uma imagem do IRIS Community Edition:

  1. Instale o Docker desktop 

  2. Execute no terminal do sistema operacional o seguinte:

docker run --rm -p 52773:52773 --init --name my-iris store/intersystems/iris-community:2020.1.0.199.0
  1. Em seguida, abra o Portal de Administração do IRIS em seu navegador host em:

http://localhost:52773/csp/sys/UtilHome.csp

  1. Ou abra uma sessão no terminal:

    docker exec -it my-iris iris session IRIS

  2. Pare o contêiner IRIS quando não precisar mais dele:

    docker stop my-iris

OK! Executamos o IRIS em um contêiner docker. Mas você deseja que um desenvolvedor instale seu código no IRIS e talvez faça algumas configurações. Isso é o que discutiremos a seguir.

Importando arquivos ObjectScript

O projeto InterSystems ObjectScript mais simples pode conter um conjunto de arquivos ObjectScript como classes, rotinas, macro e globais. Verifique o artigo sobre nomenclatura e estrutura de pastas proposta.

A questão é: como importar todo esse código para um contêiner IRIS?

Aqui é o momento em que o Dockerfile nos ajuda pois podemos usá-lo para pegar o contêiner IRIS padrão, importar todo o código de um repositório para o IRIS e fazer algumas configurações com o IRIS, se necessário. Precisamos adicionar um Dockerfile no repositório.

Vamos examinar o Dockerfile do repositório de modelos ObjectScript:

ARG IMAGE=store/intersystems/irishealth:2019.3.0.308.0-community
ARG IMAGE=store/intersystems/iris-community:2019.3.0.309.0
ARG IMAGE=store/intersystems/iris-community:2019.4.0.379.0
ARG IMAGE=store/intersystems/iris-community:2020.1.0.199.0
FROM $IMAGE

USER root

WORKDIR /opt/irisapp
RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp

USER irisowner

COPY  Installer.cls .
COPY  src src
COPY iris.script /tmp/iris.script # run iris and initial 

RUN iris start IRIS \
    && iris session IRIS < /tmp/iris.script

 

As primeiras linhas ARG definem a variável $IMAGE - que usaremos então em FROM. Isso é adequado para testar/executar o código em diferentes versões do IRIS, trocando-os apenas pelo que é a última linha antes do FROM para alterar a variável $IMAGE. 

Aqui temos: 

ARG IMAGE=store/intersystems/iris-community:2020.1.0.199.0

FROM $IMAGE

Isso significa que estamos pegando o IRIS 2020 Community Edition versão 199.

Queremos importar o código do repositório - isso significa que precisamos copiar os arquivos de um repositório para um contêiner do docker. As linhas abaixo ajudam a fazer isso:

USER root

WORKDIR /opt/irisapp
RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp

USER irisowner

COPY  Installer.cls .
COPY  src src

USER root - aqui, mudamos o usuário para root para criar uma pasta e copiar arquivos no docker.

WORKDIR  /opt/irisapp - nesta linha configuramos o diretório de trabalho no qual copiaremos os arquivos.

RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp   -  aqui, damos os direitos ao usuário e grupo irisowner que executam o IRIS.

USER irisowner - trocando usuário de root para irisowner

COPY Installer.cls .  - copiando o Installer.cls para a raiz do workdir. Não esqueça aqui do ponto.

COPY src src - copia os arquivos de origem da pasta src no repo para a pasta src no workdir no docker.

No próximo bloco, executamos o script inicial, onde chamamos o instalador e o código ObjectScript:

COPY iris.script /tmp/iris.script # executar o iris e iniciar 
RUN iris start IRIS \
    && iris session IRIS < /tmp/iris.script

COPY iris.script / - copiamos iris.script para o diretório raiz. Ele contém o ObjectScript que desejamos chamar para configurar o contêiner.

RUN iris start IRIS</span>  - inicia o IRIS

&& iris session IRIS < /tmp/iris.script - inicia o terminal IRIS e insere o ObjectScript inicial nele.

Ótimo! Temos o Dockerfile, que importa arquivos no docker. Mas nos deparamos com outros dois arquivos: installer.cls e iris.script. Vamos examiná-los.

Installer.cls

Class App.Installer
{

XData setup
{
<Manifest>
  <Default Name="SourceDir" Value="#{$system.Process.CurrentDirectory()}src"/>
  <Default Name="Namespace" Value="IRISAPP"/>
  <Default Name="app" Value="irisapp" />

  <Namespace Name="${Namespace}" Code="${Namespace}" Data="${Namespace}" Create="yes" Ensemble="no">

    <Configuration>
      <Database Name="${Namespace}" Dir="/opt/${app}/data" Create="yes" Resource="%DB_${Namespace}"/>

      <Import File="${SourceDir}" Flags="ck" Recurse="1"/>
    </Configuration>
    <CSPApplication Url="/csp/${app}" Directory="${cspdir}${app}"  ServeFiles="1" Recurse="1" MatchRoles=":%DB_${Namespace}" AuthenticationMethods="32"
       
    />
  </Namespace>

</Manifest>
}

ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ]
{
  #; Deixe o documento XGL gerar código para este método. 
  Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup")
}

}

Francamente, não precisamos do Installer.cls para importar arquivos. Isso pode ser feito com uma linha. Mas frequentemente, além de importar o código, precisamos configurar a aplicação CSP, introduzir configurações de segurança, criar bancos de dados e namespaces.

Neste Installer.cls, criamos um novo banco de dados, namespace com o nome IRISAPP e criamos a aplicação /csp/irisapp padrão para este namespace.

Tudo isso realizamos no elemento <Namespace>:

<Namespace Name="${Namespace}" Code="${Namespace}" Data="${Namespace}" Create="yes" Ensemble="no">

    <Configuration>
      <Database Name="${Namespace}" Dir="/opt/${app}/data" Create="yes" Resource="%DB_${Namespace}"/>

      <Import File="${SourceDir}" Flags="ck" Recurse="1"/>
    </Configuration>
    <CSPApplication Url="/csp/${app}" Directory="${cspdir}${app}"  ServeFiles="1" Recurse="1" MatchRoles=":%DB_${Namespace}" AuthenticationMethods="32"
       
    />
  </Namespace>

E importamos todos os arquivos do SourceDir com a tag Import:

<Import File="${SourceDir}" Flags="ck" Recurse="1"/>

SourceDir aqui é uma variável, que é definida para o diretório/pasta src atual:

<Default Name="SourceDir" Value="#{$system.Process.CurrentDirectory()}src"/>

Uma classe Installer.cls com essas configurações nos dá a confiança de que criamos um novo banco de dados IRISAPP limpo, no qual importamos código ObjectScript arbitrário da pasta src.

iris.script

Aqui, você é bem-vindo para fornecer qualquer código de configuração ObjectScript inicial que deseja para iniciar seu contêiner IRIS.

Ex. Aqui carregamos e executamos o installer.cls e então criamos o UserPasswords sem expiração, apenas para evitar a primeira solicitação de alteração da senha, pois não precisamos desse prompt para o desenvolvimento.

; run installer to create namespace
do $SYSTEM.OBJ.Load("/opt/irisapp/Installer.cls", "ck")
set sc = ##class(App.Installer).setup()  zn "%SYS"
Do ##class(Security.Users).UnExpireUserPasswords("*") ; call your initial methods here
halt

docker-compose.yml

Por que precisamos de docker-compose.yml ? Não poderíamos simplesmente construir e executar a imagem apenas com Dockerfile? Sim, poderíamos. Mas docker-compose.yml simplifica a vida.

Normalmente, docker-compose.yml é usado para iniciar várias imagens docker conectadas a uma rede.

docker-compose.yml também pode ser usado para tornar a inicialização de uma imagem docker mais fácil quando lidamos com muitos parâmetros. Você pode usá-lo para passar parâmetros para o docker, como mapeamento de portas, volumes, parâmetros de conexão VSCode.

version: '3.6' 
services:
  iris:
    build: 
      context: .
      dockerfile: Dockerfile
    restart: always
    ports: 
      - 51773
      - 52773
      - 53773
    volumes:
      - ~/iris.key:/usr/irissys/mgr/iris.key
      - ./:/irisdev/app

Aqui, declaramos o serviço iris, que usa o arquivo docker Dockerfile e expõe as seguintes portas do IRIS: 51773, 52773, 53773. Além disso, este serviço mapeia dois volumes: iris.key do diretório inicial da máquina host para a pasta IRIS onde é esperado, e ele mapeia a pasta raiz do código-fonte para a pasta /irisdev/app.

Docker-compose nos oferece o comando mais curto e unificado para construir e executar a imagem, quaisquer que sejam os parâmetros que você configurar no docker compose.

em qualquer caso, o comando para construir e lançar a imagem é:

$ docker-compose up -d

 e para abrir o terminal IRIS:

$ docker-compose exec iris iris session iris

Node: 05a09e256d6b, Instance: IRIS

USER>

Além disso, docker-compose.yml ajuda a configurar a conexão para o plugin VSCode ObjectScript.

.vscode/settings.json

A parte relacionada às configurações de conexão da extensão ObjectScript é esta:

{
    "objectscript.conn" :{
      "ns": "IRISAPP",
      "active": true,
      "docker-compose": {
        "service": "iris",
        "internalPort": 52773
      }
    }     

}

Aqui vemos as configurações, que são diferentes das configurações padrão do plugin VSCode ObjectScript.

Aqui, dizemos que queremos nos conectar ao namespace IRISAPP (que criamos com Installer.cls):

"ns": "IRISAPP",

e há uma configuração docker-compose, que informa que, no arquivo docker-compose dentro do serviço "iris", o VSCode se conectará à porta, para a qual 52773 está mapeado:

"docker-compose": {
        "service": "iris",
        "internalPort": 52773
      }

Se verificarmos o que temos para 52773, veremos que esta é a porta mapeada não definida para 52773:

ports: 
      - 51773
      - 52773
      - 53773

Isso significa que uma porta aleatória disponível em uma máquina host será obtida e o VSCode se conectará a este IRIS no docker via porta aleatória automaticamente.

Este é um recurso muito útil, pois oferece a opção de executar qualquer quantidade de imagens do docker com IRIS em portas aleatórias e ter VSCode conectado a elas automaticamente.

E quanto a outros arquivos?

Nos também temos:

.dockerignore  - arquivo que você pode usar para filtrar os arquivos da máquina host que você não deseja que sejam copiados para a imagem docker que você construir. Normalmente .git e .DS_Store são linhas obrigatórias.

.gitattributes - atributos para git, que unificam terminações de linha para arquivos ObjectScript em fontes. Isso é muito útil se o repositório for colaborado por proprietários de Windows e Mac/Ubuntu.

.gitignore - arquivos, os quais você não deseja que o git rastreie o histórico de alterações. Normalmente, alguns arquivos ocultos no nível do sistema operacional, como .DS_Store.

Ótimo!

Como tornar seu repositório executável em docker e amigável para colaboração?

  1. Clone este repositório.

  2. Copie todos esses arquivos:

Dockerfile

docker-compose.yml

Installer.cls

iris.script

settings.json{#9f423fcac90bf80939d78b509e9c2dd2-d165a4a3719c56158cd42a4899e791c99338ce73}

.dockerignore{#f7c5b4068637e2def526f9bbc7200c4e-c292b730421792d809e51f096c25eb859f53b637}
.gitattributes{#fc723d30b02a4cca7a534518111c1a66-051218936162e5338d54836895e0b651e57973e1}
.gitignore{#a084b794bc0759e7a6b77810e01874f2-e6aff5167df2097c253736b40468e7b21e577eeb}

para o seu repositório.

Altere esta linha no Dockerfile para corresponder ao diretório com ObjectScript no repositório que você deseja importar para o IRIS (ou não altere se estiver na pasta /src).

É isso. E todos (e você também) terão seu código importado para o IRIS em um novo namespace IRISAPP.

Como as pessoas irão iniciar o seu projeto

o algoritmo para executar qualquer projeto ObjectScript no IRIS pode ser:

  1. Clone o projeto Git localmente

  2. Execute o projeto:

$ docker-compose up -d
$ docker-compose exec iris iris session iris

Node: 05a09e256d6b, Instance: IRIS

USER>zn "IRISAPP"

**Como qualquer desenvolvedor pode contribuir para o seu projeto **

  1. Bifurque o repositório e clone o repositório git bifurcado localmente

  2. Abra a pasta no VSCode (eles também precisam que as extensões Docker e ObjectScript estejam instaladas no VSCode)

  3. Clique com o botão direito em docker-compose.yml->Reiniciar - VSCode ObjectScript irá conectar-se automaticamente e estará pronto para editar/compilar/depurar

  4. Commit, Push e Pull as mudanças solicitadas em seu repositório

Aqui está um pequeno gif sobre como isso funciona:

É isso! Viva a programação!

0
0 490